Vuex

作者: 黄黄黄大帅 | 来源:发表于2022-03-29 16:47 被阅读0次

    一、核心原理

    1.Vuex本质是一个对象,有两个属性,一个是install方法,一个是Store这个类。
    2.install方法的作用是将store这个实例挂载到所有的组件上,注意是同一个store实例。
    3.Store这个类拥有commit,dispatch这些方法,Store类里将用户传入的state包装成data,作为new Vue的参数,从而实现了state 值的响应式。
    4.$store是挂载在Vue实例、即Vue.prototype中,在组件中可使用 this 访问原型上的属性 如 this.$store.state.count。

    工作原理如图:


    vuex.png

    通过store.dispatch('increment')分发Action(可异步操作回调),通过Action 提交Mutation(只能同步更改数据),通过Mutation修改state里面的值

    二、伪代码

    state:{
      conut:1
    },
    mutations:{
       setDataMutation(state,payload){// 在大多数情况下,载荷payload 应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读
         state.count+=payload.count
       }
    },
    actions:{
        setDataAction(context,data){
            context.commit('setDataMutation',data)
        }
    }
    
    this.store.dispatch('setDataAction',{count:2}).then(()=>{})
    

    三、简化写法(辅助函数mapState、mapGetters 、mapMutations 、 mapActions)

    为了减少代码量...
    mapState
    • 需要从 store 实例中读取状态时,并赋予computed计算属性时
    computed:{
      count:(){
        return  this.$store.state.count
      }
    }
    
    
    • 使用 mapState
    import { mapState } from 'vuex'
    
    export default {
      computed:mapState{
         count:state => state.count
     }
    }
    
    • 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
    computed: mapState([
      // 映射 this.count 为 store.state.count
      'count'
    ])
    
    • 与局部计算属性混合使用
    computed: {
      localComputed () { /* ... */ },
      // 使用对象展开运算符将此对象混入到外部对象中
      ...mapState({
        // ...
      })
    }
    
    mapGetters
    • store 的 getter,可以认为是 store 的计算属性,用来筛选store中符合某些条件的数据
    computed: {
      doneTodosCount () {
        return this.$store.state.todos.filter(todo => todo.done).length
      }
    }
    
    • 使用getter
    const store = createStore({
      state: {
        todos: [
          { id: 1, text: '...', done: true },
          { id: 2, text: '...', done: false }
        ]
      },
      getters: {
        doneTodos: (state) => {
          return state.todos.filter(todo => todo.done)
        }
      }
    })
    
    store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
    
    • 使用mapGetters
      mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
    import { mapGetters } from 'vuex'
    
    export default {
      // ...
      computed: {
      // 使用对象展开运算符将 getter 混入 computed 对象中
        ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
        ])
      }
    }
    
    ...mapGetters({
      // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
      doneCount: 'doneTodosCount'
    })
    
    mapMutations
    • mutation 需要store实例的commit方法触发
    this.$store.commit('setDataMutation')
    
    • 使用 mapMutations
    import { mapMutations } from 'vuex'
    
    export default {
      // ...
      methods: {
        ...mapMutations([
          'setDataMutation', // 将 `this.setDataMutation()` 映射为 `this.$store.commit('setDataMutation')`
    
          // `mapMutations` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
        ]),
        ...mapMutations({
          add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
        })
      }
    }
    
    mapActions
    • 在组件中分发Action:使用 this.$store.dispatch('xxx') 分发 action

    • 使用mapActions

    import { mapActions } from 'vuex'
    
    export default {
      // ...
      methods: {
        ...mapActions([
          'setDataAction', // 将 `this.setDataAction()` 映射为 `this.$store.dispatch('setDataAction')`
    
          // `mapActions` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
        ]),
        ...mapActions({
          add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
        })
      }
    }
    

    四、使用Module

    作用:将全局数据按分类储存在不同模块中

    • 开启namespace
    // 在module中
    export default {
        namespaced: true,
        // ...
    }
    
    import moduleA from './module/moduleA';
    import moduleB from './module/moduleB';
    
    export default new Vuex.Store({
        modules: {
            moduleA, moduleB,
        },
        // ...
    }
    
    // ...
    computed: {
        ...mapState({
            name: state => state.moduleA.text
        }),
    },
    // ...
    
    computed: {
        ...mapState('some/nested/module', {
            a: state => state.a,
            b: state => state.b
        })
    },
    methods: {
        ...mapActions('some/nested/module', [
            'foo', // -> this.foo()
            'bar' // -> this.bar()
        ])
    }
    
    • createNamespacedHelpers 创建基于某个命名空间辅助函数。
    import { createNamespacedHelpers } from 'vuex'
    
    const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
    
    export default {
      computed: {
        // 在 `some/nested/module` 中查找
        ...mapState({
          a: state => state.a,
          b: state => state.b
        })
      },
      methods: {
        // 在 `some/nested/module` 中查找
        ...mapActions([
          'foo',
          'bar'
        ])
      }
    }
    
    访问根节点
    • 模块内部的 state 是局部的,只属于模块本身所有。那么如果我们要想在模块中访问 store 根节点的数据 state,怎么办呢?
    export default {
        // ...
        getters: {
            // 注意:rootState必须是第三个参数
            detail(state, getters, rootState) {
                return state.text + '-' + rootState.name;
            }
        },
        actions: {
            callAction({state, rootState}) {
                alert(state.text + '-' + rootState.name);
            }
        }
    }
    
    • 在带命名空间的模块内访问全局内容
    modules: {
      foo: {
        namespaced: true,
    
        getters: {
          // 在这个模块的 getter 中,`getters` 被局部化了
          // 你可以使用 getter 的第四个参数来调用 `rootGetters`
          someGetter (state, getters, rootState, rootGetters) {
            getters.someOtherGetter // -> 'foo/someOtherGetter'
            rootGetters.someOtherGetter // -> 'someOtherGetter'
          },
          someOtherGetter: state => { ... }
        },
    
        actions: {
          // 在这个模块中, dispatch 和 commit 也被局部化了
          // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
          someAction ({ dispatch, commit, getters, rootGetters }) {
            getters.someGetter // -> 'foo/someGetter'
            rootGetters.someGetter // -> 'someGetter'
    
            dispatch('someOtherAction') // -> 'foo/someOtherAction'
            dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
    
            commit('someMutation') // -> 'foo/someMutation'
            commit('someMutation', null, { root: true }) // -> 'someMutation'
          },
          someOtherAction (ctx, payload) { ... }
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:Vuex

          本文链接:https://www.haomeiwen.com/subject/wkzhyktx.html