美文网首页
vuex的使用

vuex的使用

作者: 瓢鳍小虾虎 | 来源:发表于2021-09-29 15:35 被阅读0次

vuex适合用于多组件共享数据的情况,多个组件都能读,也都可以改。

vuex的执行流程:

vuex的3个组成部分:action、mutation、state被封装在一个叫store的对象中,store负责管理内部各部分的互相调用,包装流程

  1. store的dispatch被调用,根据key值匹配调用action的指定方法
  2. action执行同步/异步收集数据的操作,把结果通过commit发送给指定mutation
  3. mutation调用指定方法执行state(即数据)更新行为
  4. 数据被更新后,就是vue实例开始接力了:触发了vue实例的数据代理,然后就是重新解析模板、更新dom

安装

npm install vuex --save

使用

vuex是一个插件,所以需要Vue.use

import Vuex from 'vuex'

Vue.use(Vuex)

注册了vuex,我们就可以在vue里配置store了

const store = Vuex.Store({
  state: {
    count: 0,
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

getters

这里多了个配置getters,他可以看作是基于state的computed属性。使用的方式基本如下:

  1. 直接$store.getters.xxx获取
  2. 或者通过mapGetters,本质就是把getter属性通过mixin映射到了vc组件内部,这种方式的好处是可以像本地computed属性一样直接获取,用起来更简介。
    类似的还有mapState、mapActions、mapMutations
computed: {
   ...mapGetters([
     'doneTodosCount',
     'anotherGetter',
     // ...
   ])
 }

同时getters还可以配置成函数,方便我们动态传参,满足一些复杂一点的场景

getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}

调用

$store.getters.getTodoById(2)

模块化store

随着项目迭代,需求的扩展,你的store会变得越来越臃肿,建议模块化拆分store



以上就是一些对象的拼装,但是模块要放到名为modules的属性内部,store的最终结构大致如下:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

模块的命名空间
默认模块的state、getter等属性都会合并到根级别,如果你希望模块有更好的封装性,避免多模块命名污染,可以配置上命名空间属性namespace:true

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,

      // 模块内容(module assets)
      state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模块
      modules: {
        // 继承父模块的命名空间
        myPage: {
          state: () => ({ ... }),
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 进一步嵌套命名空间
        posts: {
          namespaced: true,

          state: () => ({ ... }),
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})

使用了模块命名空间后,action和getter内部常规用法只能访问本命名空间的dispatch,commit或者getter,如果要访问全局命名空间,需要使用额外的参数和配置:

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) { ... }
    }
  }
}

模块动态注册

在 store 创建之后,你可以使用 $store.registerModule 方法注册模块

如果大多场景下,你的模块化store并不会被使用,只在你的业务流程页面中被用到,这时可以考虑在合适的生命周期节点(比如created)动态注册你的模块。同时要注意先检查模块是否已经被安装:$store.hasModule(moduleName),避免重复注册模块,不然会出现逻辑问题。你也可以卸载自己的模块:$store.unregisterModule(moduleName)

// 注册模块 `myModule` 通过store.state.myModule访问
$store.registerModule('myModule', {
  // ...
})
// 注册嵌套模块 `nested/myModule` 通过store.state.nested.myModule访问
$store.registerModule(['nested', 'myModule'], {
  // ...
})

官方文档

相关文章

网友评论

      本文标题:vuex的使用

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