我们平时都会用vuex来管理Vue项目中的全局变量,觉得方便又好用。
现在我们来更深入分析了解一下。
为什么要出现Vuex?
Vue开发的应用,页面渲染是组件粒度的,每个组件通过订阅 “响应式数据”,来更新组件渲染。组件嵌套组件形成树状结构的组件关系表。
这就出现了1个问题:如何做到多个组件共同订阅一个“响应式数据”,当其中1个组件通过监听事件对该数据做出改变,如何通知所有组件进行重新渲染?
可能有人会说,实现全局变量方式很多呀。比如往Vue.prototype.xx进行扩展定义 或者 通过window.xxx定义。但是这样有两点问题:
1、比如把window.xx赋值给组件a中响应式属性num,当我们对window.xx进行修改,并不会触发数据num的set函数,也就无法重新渲染组件。而vuex可以做到。我们可以来看个例子:
2、我们不能方便地跟踪每一个状态的变化,而vuex帮我们做到了,只要我们根据文档来操作。
我们知道,vue的组件间数据传递的方式有几种:
1、vue 2.0.3后,父子组件间数据传递支持双向流动。父组件中,通过:dataName.sync="data"把数据传给子组件,子组件通过props接受数据,子组件通过this.$emit('update:dataName', newValue)更新数据传递给父组件即可。
2、eventBus,任意组件间实现数据传递。比如两个组件a.vue和b.vue,我们先定义一个bus.js,其内引入Vue(import Vue from 'vue');暴露new Vue(export default newVue())。在两个组件中都引入bus.js(import Bus from 'common/js/bus.js';)。a组件通过Bus.$emit('funName', newVue)把数据传递出去,b组件通过Bus.$on('funName', target => {..})接受数据。
一般来说,vuex的一个store模式就够我们的简单应用使用。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
Vuex的使用
vuex的初始化,const store=new Vuex.Store({state(state:state的缩写),getters,mutations,actions})。
一、组件中获取store中状态的方法
1、在computed中获取。
可以在computed中通过store.state.count获取。缺点:组件依赖全局状态单例,在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态。
所以我们一般在new Vue时把store对象注入,在computed中通过this.$store.state.count获取。
2、当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:
例子1当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
例子2通过扩展运算符,mapState 辅助函数与局部计算属性混合使用
例子3二、getter模块的运用
上面的介绍我们已经可以直接拿到状态了,并且能把状态拿来计算(比如上面的countPlusLocalState)。
但是,我们如果在多个组件中都需要用到这种计算方法,在每个组件都要复制这个方法或者写成共享函数多处导入它,都不理想。
于是有了getter这一层。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
如何取getter中定义的计算属性:
1、在computed通过属性访问
注意,getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的。
2、可用mapGetters 辅助函数来简化操作
3、在computed通过方法访问
让 getter 返回一个函数,来实现给 getter 传参,在对 store 里的数组进行查询时非常有用。注意,getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
三、提交mutation来修改状态(同步)。
1、mutation中函数的定义 和 普通提交mutation(this.$store.commit)。
state 作为第一个参数,第二个参数是传的参数2、通过mapMutations辅助函数提交mutation(会将组件中的 methods 映射为 store.commit 调用,需要在根节点注入 store)。
mapMutations辅助函数提交mutation使用常量替代 Mutation 事件类型。
可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然。
四、提交Action来修改状态(异步)。
Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。
例子context 对象是一个与 store 实例具有相同方法和属性的对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
当我们需要调用 commit 很多次的时候:
分发 Action。
在action内异步调用操作 异步分发通过...mapActions来分发。
使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用
网友评论