最近在做一个单页面的管理后台项目,为了提高开发效率,使用了Vue框架来开发。为了使各个部分的功能,独立结构更加清晰,于是就拆分了很多组件,但是组件与组件之间数据共享成了一个问题,父子组件实现起来相对简单,prop,$emit,$on就能搞定。除此之外,有很多兄弟组件和跨多级组件,实现起来过程繁琐,在多人协同开发上,不利于统一管理,于是,开始了Vue的生态之一的Vux实践之旅。
2.概述
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。
Vuex 和单纯的全局对象有以下两点不同:
1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新;2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用
3.安装使用
3.1.使用Vue-cli开发安装vue包
cnpm install vuex --save
3.2.在src目录下创建store文件夹并创建index.js如下(src/store/index.js)
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); export default new Vuex.Store({ state: { }, getters: { }, mutations: { }, actions: { } });
然后在src文件下的main.js中使用
import Vue from 'vue' import App from './App' import store from './store' Vue.config.productionTip = false new Vue({ el: '#app', store, components: { App }, template: '<App/>' })
4.用法简介
4.1.state
state是保存共享数据的,现在改store/index.js如下:
state: { count:0 },
在components目录下创建Index.vue如:
<template> <div> {{count}} </div> </template> <script> export default { name: "index", computed:{ count(){ return this.$store.state.count; } } } </script>
结果如下:
我们可以通过组件的计算属性来保存state里面的值,那么问题来了,如果store太多的话,我们组件里面的计算属性岂不是成了这个样子:
computed:{ count(){ return this.$store.state.count; }, stateA(){ return this.$store.state.stateA; }, stateB(){ return this.$store.state.stateB; } }
这样获取共享状态的数据也没有什么问题不过看起来还是有大量的重复冗余代码,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
import {mapState} from 'vuex' export default { name: "index", computed:{ ...mapState(['count']), } }
小结:使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。
4.2.getter
有的时候我们需要对共享状态里面的某一个属性做一些处理后再使用,我们可以把数据获取后再在组件的计算属性中处理,举个例子如下:
// store/index.js state: { count:0, numbers:[0,1,2,3,4,5,6,7,8] }, // Index组件 <template> <div> {{count}} <br> {{numbers.join()}} </div> </template> <script> import {mapState} from 'vuex' export default { name: "index", computed:{ ...mapState(['count']), numbers(){ return this.$store.state.numbers.filter((item)=>{ return item>3; }) } } } </script>
结果如下:
那么问题来了,如果多个组件都要做同样的处理,我们就需要把一份代码复制到多个地方,显然是不大合理的,于是有了getter,可以理解为组件里面的计算属性。示例如下:
/ store/index.js getters: { filterNumbers(state){ return state.numbers.filter((item)=>{ return item>3; }) } }, // Index组件 <template> <div> {{count}} <br> {{filterNumbers.join()}} </div> </template> <script> import {mapState} from 'vuex' export default { name: "index", computed:{ ...mapState(['count']), filterNumbers(){ return this.$store.getters.filterNumbers; } } } </script>
结果完全一样,我们可以根据this.$store.getters.属性名来获取getters,也可以通过 mapGetters 辅助函数将 store 中的 getter 映射到局部计算属性:
具体实现方式如下: