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   // 要引用
 
})

 

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