官方文档:https://vuex.vuejs.org/zh/guide/
为什么使用vuex
在开发一个功能型的大型应用的情况下,一个项目中会有很多个组件,组件之间的层级与位置都是无法控制的,如果这个所有组件都需要一个全局的属性,并且监听这个属性的变化,vuex的作用就出现了。
组件化开发
因为vue采用组件化开发,且组件保持单一指责原则,而组件之间的通讯也因此变得很艰难。
案例1
我们用vscode来举例子。
根据组件化开发的方式,我们知道,其左侧的资源管理器为一个组件,右侧的文件选项卡为一个组件,下方的文本编辑框为一个组件。
- 资源管理器组件
- 文件选项卡组件
- 文本编辑器组件
我们可以很容易的得知,监听资源管理器的事件,然后派发给文件选项卡,文件选项卡接收事件后增加选项卡,并且当用户点击选项卡的时候,触发事件交给文本编辑器组件。
这是一个基本的流程,但我们也看到了这三个组件的严重依赖。
优化方案:
当资源管理器点击文件后,将其记录在vuex中。
文件选项卡监听vuex中当前点击的文件,并处理新增的逻辑。
文本编辑器永远只打开vuex中当前点击的文件。
这样看来,通过vuex全局记录一个属性,就可以解耦这些文件的依赖关系,比如,用户如果不是通过资源管理器打开的文件,而是通过快捷命令打开的呢,如果采用事件监听的方式,那肯定要维护很多的事件,但使用vuex的方式,每个“打开文件”的组件只需要自己维护vuex中的属性即可。
在vscode中,每打开的一个项目都是一个工程文件,且工程文件都是有相关配置和插件配置的。而每个文件都需要通过对应的插件来解析。
例如打开ts文件,vscode会根据typescript插件来解析文件,比如验证功能、类型检查功能等。
而ts的配置文件或所有的配置文件,就可以放在vuex中维护,这样文本编辑器组件就不需要自己去通过io去读取配置文件并且加载。
优化方案:
vscode打开时,启动插件检查器,并加载所有插件的配置,放入vuex中。
文本编辑器打开时,自动获取和ts关联的插件,并且把控制权交给相关的插件,而插件从vuex中读取配置,也无需自己实现io功能。
案例2
我们日常开发中,并不能接触像vscode这种级别的项目,但不代表vuex就丧失了作用。这里举一个最简单的例子。
在一些购物app中,每个页面都能看到一个购物车浮动的小icon,且上面有购物车的数量。并且在一些app中,几乎每个页面都有一个购物车的入口和数量。
我们已知,购物车的数量被很多的组件所引用,而且是需要根据购物车的数量实时变化的。如果我们在每个组件都开发一个通过接口获取数量的功能,那冗余度会很高,而且不能获取最新的数据,除非轮询。而将购物车数量保存在一个全局变量或者缓存中,vue又无法通过变量的变化来更新视图。
这个时候,vuex的作用就体现出来了。
每个需要数量的组件全部引用vuex中的购物车数量属性,且vuex的数量发生了变化,vue是可以更新视图的。
在添加购物车和删除购物车的时候,通过提交更改的方式(commit)更新数量变化。
这样,在需要更新的时候,统一调用vuex的函数,就可以全局更改数量的显示了。
起步
在src/store/
文件夹下新建index.js
import Vue from 'vue'
import Vuex from 'vuex'
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
获取count
this.$store.state.count;
为了防止随意更改state的数据造成污染,我们必须采用触发函数的方式去更改数据。
改变count
this.$store.commit('increment');
注:以上的this代表在vue实例内
模块化
import Vue from 'vue'
import Vuex from 'vuex'
import project from './modules/project'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
project: { namespaced: true,...project}
}
})
namespaced:命名空间,建议打开命名空间以更好的使用模块化的功能。
modules:注册模块
通过模块获取count
this.$store.state.project.count;
改变count
this.$store.commit('project/increment');
注:以上的this代表在vue实例内
其中,project为模块的名字。