zoukankan      html  css  js  c++  java
  • vuex学习总结

    state

    • 作用:相当于vue中的data,用于存储状态,是唯一数据源,而且是只读,不能做直接修改。从头开始学习Vuex
    • 语法:
    
    const store = new Vuex.Store({
      state: {
        text:'hello world'
      }
    })
    
    • 调用:
    
    // 方法1
    store.state.text
    // 方法2(需要使用vue.use注入)
    this.$store.state.text
    // 方法3,通过辅助函数mapState
    import { mapState } from 'vuex';
    export default {
        computed: {
            // 使用ES6的扩展运算符来达到将state释放出来
            ...mapState([
              // 映射 this.text 为 store.state.text
              'text'
            ])
        }
    }
    

    注意:如果一般state初始化时最好就设置好所需属性,如果真的需要动态需改某一个属性,可以如下:
    1)Vue.set(obj, 'newProp', 123)
    2)state.obj = { ...state.obj, newProp: 123 }

    getter

    • 作用:相当于vue中的computed,作用也是类似的。
    • 语法:
    
    const store = new Vuex.Store({
      state: {
        text:'hello world'
      },
      getters: {
        // 第一个参数固定是state对象,第二个参数固定是getters对象
        getText: (state, getters) => {
            return state.text + ' xiaoming';
        },
        // getters方法中调用getters方法
        getGettersText: (state, getters) => {
            return getters.getText;
        },
        // getters方法返回一个函数
        getFuncText: (state,getters) => (name) => {
            return state.text + ' ' + name;
        }
      }
    })
    
    • 调用:
    
    // 方法1
    store.getters.getText
    // 方法2
    this.$store.getters.getText
    // 方法3,通过辅助函数mapGetters
    import { mapGetters } from 'vuex'
    export default {
        computed: {
            ...mapGetters([
                'getText',
                'getGettersText',
                'getFuncText'
            ])
        }
    }
    

    mutation

    • 作用:相当于vue中data对象的的set方法,是唯一可以改变state数据的方式,定位是同步改变,即在mutation的方法中不支持异步逻辑,这个的具体原因是因为mutation类似于事件监听的回调函数,而任何在回调函数中进行的状态的改变都是不可追踪的。
    • 语法:
    
    const store = new Vuex.Store({
      state: {
        text:'hello world'
      },
      mutations: {
        // 第一个参数固定是state,剩下还可以再传入一个或0个参数(也叫载荷),这个载荷参数一般是对象,方便传入多个值
        changeText (state, payload) {
          // 变更状态
          state.text = 'welcome' + payload.name;
        }
      }
    })
    
    • 调用:
    
    // 方法1,只是第二个参数是载荷
    store.commit('changeText', {
        name: 'xiaoye'
    })
    // 方法2,相当于整个对象都是载荷
    store.commit({
        type: 'changeText',
        name: 'xiaoye'
    })
    // 方法3
    this.$store.commit('changeText', {
        name: 'xiaoye'
    })
    
    // 方法4,依赖辅助函数mapMutations 
    import { mapMutations } from 'vuex';
    export default {
      methods: {
      // 将this.changeText({name: 'xiaoye'})映射为this.$store.commit('changeText', {name: 'xiaoye'});
        ...mapMutations([
          'changeText'
        })
      }
    }
    

    action

    • 作用:相当于vue中的method,不能直接修改state,只能通过调用mutation中的方法间接改变state,定位是异步改变,当然也可以同步,如果是需要异步改变的逻辑建议写在action中,其实用过action就知道,其实就相当于把本来属于vue中的method中的方法放到vuex中的action中来而已,只是说公共的异步请求不再用写那么多份在不同的method中,只需要写一份放在action中即可。
    • 语法:
    
    const store = new Vuex.Store({
      state: {
        text:'hello world'
      },
      mutations: {
        // 第一个参数固定是state,剩下还可以再传入一个或0个参数(也叫载荷),这个载荷参数一般是对象,方便传入多个值
        changeText (state, payload) {
          // 变更状态
          state.text = 'welcome' + payload.name;
        }
      },
      actions: {
        // 第一个参数是固定的一个类似store的实例,具有和store实例相同方法和属性,即可以直接调用state,getters,commit,dispatch等;第二个参数同mutations一样,是载荷
        asynChangeText (context, payload) {
            setTimeout(() => {
              context.commit('changeText', payload.asynName)
            }, 1000)
        }
      }
    })
    
    • 调用:
    
    // 方法1
    store.dispatch('asynChangeText', {
      asynName: 'xiaoMing'
    })
    
    // 方法2
    store.dispatch({
      type: 'asynChangeText',
      asynName: 'xiaoMing'
    })
    
    // 方法3
    this.$store.commit('asynChangeText', {
        asynName: 'xiaoMing'
    })
    
    // 方法4,依赖辅助函数mapActions
    import { mapActions } from 'vuex';
    export default {
      // 用法同 mutation 一样
      methods: {
        ...mapActions([
          'asynChangeText'
        })
      }
    }
    

    module

    • 作用:将state模块化和嵌套子模块化,避免state过大,而变得臃肿,不方便管理,每一个模块都包含完整的state、actions、mutations、getters。
    • 语法1(默认命名空间):
    
    /**
     ** 模块化(默认命名空间)
     */
    const moduleA = {
      state: {
        a: 1,
      },
      mutations: {
        // 该state包含的是本模块自己以及子模块的state
        setA (state, payload) {}
      },
      actions: {
        // 该context除包含本模块自己以及子模块的属性和方法外,还另外多包含rootGetters和rootState两个属性根模块(moduleA)的state和getter
         getAsynA (context, payload) {}
      },
      getters: {
        // 这里的rootState和rootGetter等同于根模块(moduleA)的state和getter
        getA (state, getters, rootState, rootGetter) {}
      },
      // 两个子模块
      modules: {
        moduleB,
        moduleC
      }
    }
    
    // 和moduleA模块一样,只是rootState和rootGetter依然表示moduleA这个跟模块而已
    const moduleB = {
      state: {  },
      mutations: { ... },
      actions: { ... }
    }
    // 同moduleB
    const moduleC = {
      state: { ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store(moduleA)
    

    注意:在默认的命名空间中:
    1)所有的模块和子模块的mutations和actions都是包含在全局中的,也叫在全局命名空间中。也就是说如果不同的模块中有相同的actions或者mutations是会存在重复注册挂载到全局中的情况的,只不过他们不是覆盖而是追加的关系而已,被调用的顺讯也是按照模块的注册顺序递归调用的。

    2)所有模块和子模块的getters都是包含在全局中的,不过不同的是如果出现不同模块之间重名的情况,不是追加而是先到先得,即哪一个模块先注册,即使用谁的。

    3)而state是仍然是划分模块的,外部如果要调用,调用方式也是按照模块的层级路径来调用的。即:moduleA的状态:store.state;moduleB的状态:store.state.moduleB

    • 调用:
    
    // 调用state,方法1
    store.state.a
    store.state.moduleB.b
    // 调用state,方法2
    this.$store.state.a
    this.$store.state.moduleB.b
    // 调用state,方法3
    import {mapState} from 'vuex';
    export default {
        computed: {
            ...mapState([
                'a',        // 是moduleA的state
                'moduleB',   // moduleB是一个对象,包含自己以及子模块的state
                'c': state => state.a.moduleC.c // moduleC模块下的state可以通过这种方法的形式返回值
            ])
        }
    }
    
    // 调用getter,方法1
    store.getters.getA
    store.getters.getB
    // 调用getter,方法2
    this.$store.getters.getA
    this.$store.getters.getB
    // 调用getter,方法3
    import { mapGetters } from 'vuex'
    export default {
        computed: {
            ...mapGetters([
                'getA',
                'getB'
            ])
        }
    }
    
    // 调用mutations,方法1,和getter相同点都是挂载在全局中,不同点是不同模块中存在相同名称是会按顺序触发的
    store.commit('setA')
    store.commit('setB')
    // 调用mutations,方法2
    store.commit({
        type: 'setA'
    })
    // 调用mutations,方法3
    this.$store.commit('setA')
    // 调用mutations,方法4
    import { mapMutations } from 'vuex';
    export default {
      methods: {
        ...mapMutations([
          'setA'
        })
      }
    }
    
    // 调用actions,同mutations一样
    
    • 语法2(命名空间):
    
    /**
     ** 模块化(命名空间)
     */
    const moduleA = {
      namespaced: true,
      state: {
        a: 1,
      },
      mutations: {
        // 该state包含的是本模块自己以及子模块的state
        setA (state, payload) {}
      },
      actions: {
        // 该context除包含本模块自己以及子模块的属性和方法外,还另外多包含rootGetters和rootState两个属性根模块(moduleA)的state和getter
         getAsynA (context, payload) {}
      },
      getters: {
        // 这里的rootState和rootGetter等同于根模块(moduleA)的state和getter
        getA (state, getters, rootState, rootGetter) {}
      },
      // 两个子模块
      modules: {
        moduleB,
        moduleC
      }
    }
    
    // 和moduleA模块一样,只是rootState和rootGetter依然表示moduleA这个跟模块而已
    const moduleB = {
      //  namespaced: true, // 这里如果不设置命名空间的话那moduleC就继承父命名空间
      state: {  },
      mutations: { ... },
      actions: { ... }
    }
    // 同moduleB
    const moduleC = {
      namespaced: true,
      state: { ... },
      mutations: { ... },
      actions: { ... },
      modules: {
            moduleD: {
                namespaced: true,
                state: {
                    d: 1,
                },
                mutations: {},
                actions: {}
            }
        }
    }
    
    const store = new Vuex.Store(moduleA)
    

    注意:在命名空间中:
    1)所有的模块和子模块的mutations、actions、getters都是包含在各自的命名空间或父命名空间中,即自动根据模块注册的路径调整命名

    2)而state不受影响,因为默认state也已经是层级嵌套的了。

    • 调用
    
    // 调用state,方法4(前三个方法和默认命名空间类似)
    computed: {
      ...mapState('moduleC/moduleD', {
        d: state => state.d
      }),
      ...mapState('moduleC/moduleD', ['d']) // 这两种是一样的,只是写法不同
    },
    // 调用state,方法5(通过辅助函数createNamespacedHelpers)
    import { createNamespacedHelpers } from 'vuex';
    const { mapState } = createNamespacedHelpers('moduleC/moduleD');
    export default {
      computed: {
        // 在 `moduleC/moduleD` 中查找
        ...mapState({
          d: state => state.d
        })
      }
    }
    
    // 其他的getter、mutations、actions也是和state类似的以上的方法
    

    plugins

    • 作用:plugins 是vuex中的一个函数,一般配合 subscribe 函数实现类似于拦截器的效果,而且是一个成功之后的拦截器,是每次 mutation 调用成功之后的钩子,它接收store 实例作为作为唯一的参数。
    • 语法:
    
    const myPlugin = store => {
        // mutation 的格式为:{ type, payload },通过这个对象可以判断是哪一个 mutation 被调用了,额外的参数是什么。
        store.subscribe((mutation, state) => {
            if (mutation.type === 'updateA') {
                console.log(mutation)
                console.log(state)
            }
        })
    }
    const moduleA = {
        state: {
            a: 1,
        },
        mutations: {
            // 被调用完成之后会触发 myPlugin 中的 subscribe 回调
            updateA (context, payload) {
                console.log('A')
            }
        },
        actions: {...},
        getters: {...},
        modules: {...},
        plugins: [myPlugin]
    }
    
    export default new Vuex.Store(moduleA);
    

    注意:在插件中如果要修改state状态,也需要通过store调用commit,从而触发 mutation 改变state的状态,也就是说不能直接修改state状态。

    strict

    • 上面一直强调就是修改只能在 mutations 中完成,为了强制约束,可是在vuex实例化的时候传入该属性(严格模式)。
    • 语法
    
    const moduleA = {
        state: {...},
        mutations: {...},
        actions: {...},
        getters: {...},
        modules: {...},
        plugins: [...],
        strict: true
    }
    
    export default new Vuex.Store(moduleA);
    

    原文地址:https://segmentfault.com/a/1190000013133924

  • 相关阅读:
    OpenStack-Ocata版+CentOS7.6 云平台环境搭建 — 2.安装配置OpenStack基础服务
    OpenStack-Ocata版+CentOS7.6 云平台环境搭建 — 1.操作系统环境配置
    ssh免密登录
    PHP实现识别带emoji表情的字符串
    算法-PHP实现八大算法
    项目总结-第一次外包项目2-项目相关
    PHP.52-TP框架商城应用实例-前台4-商品详情页-面包屑导航、AJAX浏览历史
    PHP.51-TP框架商城应用实例-前台3-楼层推荐、TP框架雪崩问题
    PHP.50-TP框架商城应用实例-前台2-商品推荐
    PHP.49-TP框架商城应用实例-前台1-公共布局、制作首页
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9923611.html
Copyright © 2011-2022 走看看