vuex 的突然頓悟

    之前看vuex的教程,看了好幾遍,還是沒有能夠理解到底是怎麼用,覺得自己有點笨。

    昨天看vue教程 規模化-簡單狀態管理起步使用,看到一句話後(見下面紅字),頓然醒悟 

    組件不允許直接修改屬於 store 實例的 state,而應執行 action 來分發 (dispatch) 事件通知 store 去改變

    帶着這句話,再次看vuex教程

先放store文件中,index.js代碼



const store = new Vuex.Store({
    state: {
      count: 0,
      todos: [
        { id: 1, text: '...', done: true },
        { id: 2, text: '...', done: false }
      ]
    },
    getters: {
        doneTodos: state => {
                console.log("test")
            return state.todos.filter(todo => todo.done)
        },
        doneTodosCount: (state, getters) => {
            console.log("test2")
            return state.todos.filter(todo => todo.done)
          }
    },
    mutations: {
      increment (state) {
        state.count++
      },
      [SOME_MUTATION] (state, params) {
          let param = {...params}
          
          console.log(param.title)
      }
    }
  })
 
 

1.State

   存儲各種變量

   看,index.js代碼

  state: {
      count: 0,
      todos: [
        { id: 1, text: '...', done: true },
        { id: 2, text: '...', done: false }
      ]
    },

 再看,test.vue代碼

記住使用state裏面的屬性,要引用 mapState(見下)

// 在單獨構建的版本中輔助函數爲 Vuex.mapState
import { mapState } from 'vuex'

記住!記住!mapState中簡寫的屬性名和state中一樣

// 代碼片段,後期會附上整段代碼
 computed: {
    ...mapState([
    // 映射 this.count 爲 store.state.count
         'count'
    ])
 },
 mounted(){
    console.log(this.count) // 對應mapState中的count

  }

2.Getter

一開始的組件代碼中有此屬性緩存

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

假設這個屬性值需要用到多個組件,你就得在每個組件中複製同樣的代碼,或者抽取到一個共享函數然後在多處導入它。噹噹噹,你就需要Getter來管理咯

看,store文件夾中index.js

 getters: {
        doneTodos: state => {
                console.log("test")
            return state.todos.filter(todo => todo.done)
        },
        doneTodosCount: (state, getters) => {
            console.log("test2")
            return state.todos.filter(todo => todo.done)
          }
    },

 

再看,test.vue文件中

記住使用getter裏面的屬性,要引用 mapGetters(見下)

import { mapGetters } from 'vuex';

記住!記住!mapGetters中簡寫的屬性名和getters中一樣

  computed: {

    ...mapGetters([
      'doneTodosCount'  //對應getters裏面的方法
     
    ])
  },

 

3.Mutation

 更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。(就是你要更改state中的值,需要通過mutation改)

看,store文件夾中index.js

    mutations: {
      increment (state) {  // increment爲函數名
        state.count++
      }
    }

類似於method中定義事件

 

再看,test.vue文件中

記住使用mutation裏面的方法,要引用 mapMutations(見下)

import { mapMutations } from 'vuex';

那它的引用,放在哪裏呢?就放在methods,想象下mutation裏是不是就是調用方法去改變state中內容

  methods:{
    ...mapMutations([
      'increment'
  ]),

使用常量替代 Mutation 事件類型(去官網看)

 

4.Action

Action 類似於 mutation,不同在於:

  • Action 提交的是 mutation,而不是直接變更狀態。
  • Action 可以包含任意異步操作。

當你mutation中的某個幾個方法需要同步,可以使用async/await

看,store文件夾中index.js

  actions: {
 
        incrementTest ({ commit }) {  // 普通調用
        console.log( "action" )
          commit('increment')  // increment 對應爲mutation中調用同名方法
        },
        async actionA ({ commit }) {  // 帶有異步/同步的寫法
            commit('increment', await getTest())  // getTest爲外部API函數
            console.log("actionA")
        },
        async actionB ({ dispatch, commit }) {
            await dispatch('actionA') // 等待 actionA 完成
            commit('increment', await getOtherData()) // getOtherData爲外部API函數
        }
    }

再看,test.vue

記住actions使用裏面的方法,要引用 mapActions(見下)

import {  mapActions } from 'vuex';

  methods:{

    ...mapActions([
      'incrementTest', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`
      'actionA',
      'actionB'
    ])

  }

 

test.vue整合的全部代碼

<template>
  <div class="Test">

    {{ count }}
 
  {{doneTodosCount}}
  </div>
</template>


<script>

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';

export default {
  name: 'Test',
  data () {
    return {
     
    }
  },
  computed: {
    ...mapState([
    // 映射 this.count 爲 store.state.count
         'count'
      ]),
    ...mapGetters([
      'doneTodosCount'
      // ...
    ]),
  },
  mounted(){
    console.log(this.count)
    this.SOME_MUTATION({title:"testig"})
    this.incrementTest()
  },
  methods:{
    ...mapMutations([
      'SOME_MUTATION'
    ]),
    ...mapActions([
      'incrementTest', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`
      'actionA',
      'actionB'
    ])
      

  }
}
</script>


<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>




</style>

 

index.js代碼

import Vue from 'vue'
import Vuex from 'vuex'
import  { SOME_MUTATION } from './mutation-types.js'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
      count: 0,
      todos: [
        { id: 1, text: '...', done: true },
        { id: 2, text: '...', done: false }
      ]
    },
    getters: {
        doneTodos: state => {
                console.log("test")
            return state.todos.filter(todo => todo.done)
        },
        doneTodosCount: (state, getters) => {
            console.log("test2")
            return state.todos.filter(todo => todo.done)
          }
    },
    mutations: {
      increment (state) {

        state.count++;
        console.log(state.count)
      },
   
   
      [SOME_MUTATION] (state, params) {
          let param = {...params}
          
          console.log(param.title)
      }
    },
    actions: {
 
        incrementTest ({ commit }) {
        console.log( "action" )
          commit('increment')
        },
        async actionA ({ commit }) {
            commit('increment', await getTest())
            console.log("actionA")
        },
        async actionB ({ dispatch, commit }) {
            await dispatch('actionA') // 等待 actionA 完成
            commit('increment', await getOtherData())
        }
    }
  })

 // store.dispatch('incrementTest')


//   console.log( JSON.stringify(store.getters.doneTodos))

//   store.dispatch('increment')

//   console.log(store.state.count) // -> 1

  export default store

 

main.js


import store from './store' // 導入vuex文件


/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>',
  store   // 要引用
 
})

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章