Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。通俗说Vuex 可以处理共享数据,多个组件同一份数据的操作。
Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
-
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
-
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
- 数据的异步,本地存储,外部数据的操作,使用 (dispatch) action
定义vuex 调用文件 config.js
import vuex from "vuex"; // 导入 // 安装 Vue.use(vuex); //创建 var store=new vuex.Store({ state:{ channels:{ data:[], isLoading:false, }, loginUser:[ data:[], isLogin:false, ] } }); export default store;
如果多个数据,模块定义比较清晰
命名空间:默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
// channels.js 文件 export default{ //通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。 namespaced:true,// 开启命名空间 state:{ data:[], isLoading:false, }, mutations:{ // 唯一可以数据变化的地方,不可有副作用 // state 原来的状态 payload 负荷 setData(state,payload){ state.data=payload; } }, actions:{ //可有副作用 外部数据,异步,本地存储 fetchData(context){ // 发送远程请求获取数据 var getData=getNewList(); // import getNewList form ../server/new; //context 是当前命名空间, commit 触发 mutations 里的方法 , *.vue文件中js调用当前方法 this.$store.dispatch('channels/fetchData'); context.commit("setData",getNewList) } } }; //------------------------------------------------------------------------------------- // config.js 文件, import channels from 'channels' var store=new vuex.Store({ modules:{ //a:channels 或者使用下面的方式,等同于 channels:channels channels } }); export default store;
channels.vue 模板中获取共享数据
//模板中直接 读取仓库数据 {{$store.state.channels.data}} //组件中使用仓库数据 // 单独直接调用,比较繁琐 export default{ computed:{ data(){ return this.$store.state.channels.data } } } // 使用 mapState 辅助函数 处理 属性 import {mapState} from 'vuex'; // 直接调用 export default{ computed:mapState("channels",["data","isLoading"]); } // 或者 传一个字符串数组 var computed:mapState("channels",["data","isLoading"]); computed.abc=function(){ result 123; } export default{ computed, } // 或者 对象展开运算符,与局部计算属性混合使用 export default{ computed:{ ...mapState("channels",["data","isLoading"]), abc(){ return 123; } }, created(){ // 调用更新仓库数据 命名空间,新的数据 this.$store.commit('channels/setData',[1,2,3]); // 触发 仓库 actions this.$store.dispatch('channels/fetchData'); } }
“getter” 对 store 属性处理
getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { // Getter 接受当前 state 作为其第一个参数 doneTodos: state => { // 处理属性数据 return state.todos.filter(todo => todo.done) }, // Getter 也可以接受其他 getter 作为第二个参数 doneTodosCount: (state, getters) => { return getters.doneTodos.length }, // 通过方法访问 getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } }); // *.vue js 中访问属性,Getter 会暴露为 store.getters 对象 store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }] store.getters.doneTodosCount // -> 1 // 在任何组件中使用它 computed: { doneTodosCount () { return this.$store.getters.doneTodosCount } } // 通过方法访问的调用,注意,getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果 store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:
const moduleA = { // ... getters: { sumWithRootCount (state, getters, rootState) { return state.count + rootState.count } } }
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
// *.vue js 中使用 import { mapGetters } from 'vuex' export default { // ... computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // 将一个 getter 属性另取一个名字,使用对象形式,把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount` doneCount: 'doneTodosCount' // ... ]) } }