💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 一、概述 Vuex 是一个专为 Vue.js 应用程序开发的**状态管理模式**。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 独立安装: ``` npm install vuex --save ``` 详细api参考:[https://vuex.vuejs.org/zh/api/#vuex-store](https://vuex.vuejs.org/zh/api/#vuex-store) ## 二、原理 Vuex 应用的核心就是 store(仓库)。store基本上就是一个容器,它包含着你的应用中大部分的状态 (state) 。核心是由以下五步法组成: 1. State:Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态; 2. Getter:Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。Getter 会暴露为 store.getters 对象: 3. Mutation:Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,payload作为第二个参数(额外的参数):***mutation 必须是同步函数***;Mutation 通过 `store.commit` 触发; 4. Action:Action 类似于 mutation,Action 提交的是 mutation,而不是直接变更状态Action 可以包含任意异步操作;Action 则通过 `store.dispatch` 方法触发 5. Module:Vuex 使用的是单一状态树,应用的所有状态会集中到一个对象中。如果项目比较大,那么相应的状态数据肯定就会更多,这样的话,store 对象就会变得相当的臃肿,非常难管理。因此,引入module来进行模块化管理; #### 注意: >[danger] >1、组件通过 Dispatch 调用 Actions,Actions 通过 Commit 调用 Mutations,Mutations 更改 State 数据状态,最后返回给组件 渲染视图; ![](https://img.kancloud.cn/17/3a/173afe04ab9b6ca464780296a46377e6_618x480.png) 2、当然,在实际应用中,这五个部分并不是必须的,你需要用到什么就添加什么。但是一般再怎么简单的 Vuex,也至少会由 State 和 Mutation 构成; 3、你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。 ## 三、实例 ~~~ <!--父组件中引入子组件--> <template> <div> <a href="javascript:;" @click="$store.state.show = true">点击</a> <t-dialog></t-dialog> </div> </template> <script> import dialog from './components/dialog.vue' export default { components:{ "t-dialog":dialog } } </script> <!--子组件--> <template> <el-dialog :visible.sync="$store.state.show"></el-dialog> </template> <script> export default {} </script> ~~~ ## 四、实战 工程化的实践方案; 1、在项目的src目录下新建一个目录store,在该目录下新建一个index.js文件,我们用来创建vuex实例,然后在该文件中引入vue和vuex,创建Vuex.Store实例保存到变量store中,最后使用export default导出store: ``` import Vue from 'vue' import vuex from 'vuex' Vue.use(vuex); export default new vuex.Store({ state:{ show:false } }) ``` 2、在main.js文件中引入该文件,在文件里面添加 import store from ‘./store’;,再在vue实例全局引入store对象; ``` //vuex import store from './store' new Vue({ el: '#app', router, store,//使用store template: '<App/>', components: { App } }) ``` >[danger] 这里`$store.state.show`无论哪个组件都可以使用 , 那组件多了之后 , 状态也多了 , 这么多状态都堆在 store 文件夹下的`index.js`不好维护怎么办,所以,继续优化处理; > 3、我们可以使用 vuex 的`modules`, 把 store 文件夹下的`index.js`改成 : ``` import Vue from 'vue' import vuex from 'vuex' Vue.use(vuex); import dialog_store from '../components/dialog_store.js';//引入某个store对象 export default new vuex.Store({ modules: { dialog: dialog_store } }) ``` 4、这里我们引用了一个`dialog_store.js`, 在这个 js 文件里我们就可以单独写 dialog 组件的状态了 : ``` export default { state:{ show:false } } ``` 做出这样的修改之后 , 我们将之前我们使用的`$store.state.show`统统改为`$store.state.dialog.show`即可。 >[danger] 如果还有其他的组件需要使用 vuex , 就新建一个对应的状态文件 , 然后将他们加入 store 文件夹下的 index.js 文件中的`modules`中。 ~~~ modules: { dialog: dialog_store, other: other,//其他组件 } ~~~ 5、前面我们提到的对话框例子 , 我们对vuex 的依赖仅仅只有一个 $store.state.dialog.show 一个状态 , 但是如果我们要进行一个操作 , 需要依赖很多很多个状态 , 那管理起来又麻烦,通过引入mutations 解决问题; ``` export default { state:{//state show:false }, mutations:{ switch_dialog(state){//这里的state对应着上面这个state state.show = state.show?false:true; //你还可以在这里执行其他的操作改变state } } } ``` 使用 mutations 后 , 原先我们的父组件可以改为 : ``` <template> <div id="app"> <a href="javascript:;" @click="$store.commit('switch_dialog')">点击</a> <t-dialog></t-dialog> </div> </template> <script> import dialog from './components/dialog.vue' export default { components:{ "t-dialog":dialog } } </script> ``` 使用`$store.commit('switch_dialog')`来触发`mutations`中的`switch_dialog`方法。这里需要注意的是: A、mutations中的方法是不分组件的 , 假如你在 dialog\_stroe.js 文件中的定义了 switch_dialog方法 , 在其他文件中的一个switch_dialog方法 , 那么$store.commit('switch_dialog')会执行所有的switch_dialog方法。 B、`mutations`里的操作必须是同步的。 6、多个`state`的操作 , 使用`mutations`会来触发会比较好维护 , 那么需要执行多个 mutations 就需要用`action`了; ``` export default { state:{//state show:false }, mutations:{ switch_dialog(state){//这里的state对应着上面这个state state.show = state.show?false:true; //你还可以在这里执行其他的操作改变state } }, actions:{ switch_dialog(context){//这里的context和我们使用的$store拥有相同的对象和方法 context.commit('switch_dialog'); //你还可以在这里触发其他的mutations方法 }, } } ``` 7、 getters getters 和 vue 中的 computed 类似 , 都是用来计算 state 然后生成新的数据 ( 状态 ) 的。 8、mapState、mapGetters、mapActions 这些是辅助函数;很多时候 ,$store.state.dialog.show$store.dispatch('switch_dialog')这种写法又长又臭 , 很不方便 , 我们没使用 vuex 的时候 , 获取一个状态只需要this.show, 执行一个方法只需要this.switch_dialog就行了 , 使用 vuex 使写法变复杂了。使用mapState、mapGetters、mapActions就不会这么复杂了。mapGetters、mapActions 和 mapState 类似 ,mapGetters一般也写在computed中 ,mapActions一般写在methods中。