• 六、Vuex Module


    Module 模块

    Vuex 允许将 store 分割成模块(module), 每个模块拥有自己的state、mutation、action、getter甚至是嵌套子模块, 从上至下进行同样方式的分割。分割的好处是让代码更加清晰, 易于维护管理.

    模块划分及访问

    // A 模块
    const moduleA = {
        state: {},
        getters: {},
        mutations: {},
        actions: {}
    }
    
    // B 模块
    const moduleB = {
        state: {},
        getters: {},
        mutations: {},
        actions: {}
    }
    
    const store = new Vuex.Store({
        modules: {
            a: moduleA,
            b: moduleB
        }
    });
    
    // 访问独立模块的状态
    store.state.a // 访问 moduleA 的状态
    store.state.b // 访问 moduleB 的状态
    

    模块的局部状态

    • 模块内部的 mutation、getter 的第一个参数为模块的局部状态对象
    • 模块内部的 action中, 局部状态通过 context.state 暴露, 根节点点状则为 content.rootState
    • 模块内部的 getter, 根节点的状态会作为第三个参数暴露出来
    const moduleA = {
        getters: {
            getCount (state, getters, rootState) {
                // state 局部状态
                // 局部 getters, 
                // rootState 根节点状态
                return state.count + rootState.count;
            }
        },
        mutations: {
            increment (state) {
                state.count++;
                // state 模块的局部状态
            }
        },
        actions: {
            increment ({ state, commit, rootState }) {
                // state 局部状态
                // rootState 根节点状态
                commit('increment');
            }
        }
    }
    

    命名空间

    默认情况下, 模块内部的 action、mutation、getter 是注册在全局命名空间的, 这样使得多个模块能够对同一mutation或action作出响应

    如果希望你的模块具有更高的封装和复用性, 你可以通过天剑 namespaced: true 的方式使其成为带命名空间的模块。
    当模块被注册后, 所有 getter、action及mutation 都会自动根据模块注册的路径调整命名。

    const store = new Vuex.Store({
        modules: {
            account: {
                namespaced: true,
    
                // 模块内容
                sstate: {},
                getters: {
                    inAdmin () {} // getters['account/isAdmin']
                },
                mutations: {
                    login () {} // commit('account/login')
                },
                actions: {
                    login () {} // dispatch('account/login')
                },
    
                // 嵌套模块
                modules: {
                    // 继承父模块的命名空间
                    myPage: {
                        state: {},
                        getters: {
                            profile () {} // getter['account/profile']
                        }
                    },
                    // 进一步嵌套命名空间
                    posts: {
                        namespaced: true,
                        state: {},
                        getters: {
                            popular () {} // getter['account/posts/popular']
                        }
                    }
                }
            }
        }
    });
    

    在带命名空间的模块内访问全局内容

    • 使用全局的 state 和 getter, rootState 和 rootGetters 会作为第三和第四参数传入 getter, 也会通过 context 对象的属性传入action
    • 分发和提交全局命名空间的action、mutation, 将 { root: true } 作为第三参数传给 dispatch 或 commit 即可
    modules: {
        foo: {
            namespaed: true, 
            getters: {
                someGetter (state, getters, rootState, rootGetters) {
                    getters.someOther // 'foo/someOther'
                    rootGetters.someOhter // 'someOther'
                }
            },
            actions: {
                someAction ({ dispatch, commit, getters, rootGetters }) {
                    dispatch('someOtherAction') // 'foo/someOhterAction'
                    dispatch('someOtherAction', null, { root: true }) // 'someOhterAction' 派发根节点的 action
    
                    commit('someMutation') // 'foo/someMutation'
                    commit('someMutation', null, { root: true }) // 'someMutation' 提交根节点的 mutation
                }
            }
        }
    }
    

    在命名空间模块中注册全局 action

    action: {
        someAction: {
            root: true, // 将注册到全局中
            handler () {}
        }
    }
    

    带命名空间的模块如何使用

    当使用 mapState、mapGetters、mapActions、mapMutations时需要注意

    // 方式一: 统一编写
    computed: {
        ...mapState({
            a: state => state.some.nested.module.a,
            b: state => state.some.nested.module.b
        })
    },
    methods: {
        ...mapActions([
            // this['some/nested/module/foo']()
            'some/nested/module/foo',
            'some/nested/module/bar'
        ])
    }
    
    // 方式二: 将模块的空间名称作为第一个参数,自动绑定模块上下文
    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, mapAction } = createNamespacedHelpers('some/nested/module');
    
    export default {
        computed: {
            ...mapState({
                a: state => state.a,
                b: state => state.b
            })
        },
        methods: {
            ...mapActions([
                'foo',
                'bar'
            ])
        }
    }
    
  • 相关阅读:
    分子动力学中步长的选取
    提高编程能力刷题网站
    【18】如何把数据存储到MongoDB数据库
    【17】有关python面向对象编程的提高【多继承、多态、类属性、动态添加与限制添加属性与方法、@property】
    【16】有关python面向对象编程
    【15】杂记章节
    【14】文件读取并格式化处理
    【13】python time时间模块知识点备查
    【11】python 递归,深度优先搜索与广度优先搜索算法模拟实现
    6380. 【NOIP2019模拟2019.10.06】小w与最长路(path)
  • 原文地址:https://www.cnblogs.com/yuxi2018/p/11966812.html
Copyright © 2020-2023  润新知