vuex是一个专为vue.js应用程序开发的状态管理模式,并附带了更多以的概念和框架,需要对短期和长期效益进行权衡
vuex的优点:方便的解决多组件的共享状态
他是独立于组件而单独存在的,所有的组件都可以把它当做一座桥梁来进行通讯
特点:
响应式的,只要数据修改了 ,所有用到该数据的地方,自动更新(数据驱动)
操作更简洁,逻辑清晰
核心概念
(1) state 状态树
vuex提出使用单一状态树,什么是单一状态树,英文名称是Single Source of Truth 也可以翻译为单一数据源
(2) getters 携带 state参数
类似于计算属性
(3) mutations 状态更新 携带最多两个参数,第一个默认是state参数 (注意:不能写异步内容)
修改state的值肯定是在mutations中进行,参数被称为是mutation的载荷(Payload)
(4) actions 类似于mutation,
是用来替代mutation进行异步操作的,可以解决mutation同步函数问题
(5) modules
1.因为使用单一状态树,也就意味着很多模块都会交给vuex来管理
2.当应用变得非常复杂时,store对象就会变得相当臃肿
3.为了解决该问题,vuex允许我们将store分割成模块,而每个模块拥有自己的state,mutations,actions,getters等
操作案例
注意点:
getters:
1.有一个默认参数 state
2.必须有一个返回值
mutations:
1.最多两个参数,第一个默认参数是 state
2.在使用是,看是否有分模块,如果有模块,注意添加模块名
3.通过commit 进行调用,通过在actions中context.commit 去调用
扩展: 一个模块中提交另一个模块的mutation,加这个配置项 {root:true}
store.commit('permission/setRoutes',[],{root:true}) 注意: [] 是传过去的参数, {root:true}不是参数,仅仅作为配置项
actions:
1.最多两个参数,第一个默认参数是 context
非常注意点:这里是处理异步内容的,但是修改state的值,还是要在mutations中写,通过context.commit('mutationns中的方法名')
2.通过dispatch进行调用
add-item.vue
<template> <div class="add"> add内容 <hr /> 姓名:{{ $store.state.Add.addObj.name }} <hr /> 年龄:{{ $store.state.Add.addObj.age }} <hr /> 列表信息:{{ $store.getters["Add/aList"] }} <hr /> <button @click="addOne">加一岁</button> <button @click="addN">加N岁</button> <button @click="addOneAsync">异步加一岁</button> </div> </template> <script> export default { name: "", data() { return {}; }, components: {}, methods: { addOne() { this.$store.commit("Add/addOne"); }, addN() { this.$store.commit("Add/addN", 10); }, addOneAsync() { this.$store.dispatch("Add/addOneAsync"); } } }; </script> <style scoped> .add { border: 1px solid red; } </style>
sub-item.vue
<template> <div class="sub"> sub内容 <hr /> 姓名:{{ subObj.name }} <hr /> 年龄:{{ subObj.age }} <hr /> 数据列表:{{ sList }} <hr /> <button @click="subOne">加一岁</button> <button @click="subN(10)">加N岁</button> <button @click="subOneAsync">异步加一岁</button> </div> </template> <script> import { mapState, mapGetters, mapMutations, mapActions } from "vuex"; export default { name: "", data() { return {}; }, computed: { ...mapState("Sub", ["subObj"]), ...mapGetters("Sub", ["sList"]) }, methods: { ...mapMutations("Sub", ["subOne", "subN"]), ...mapActions("Sub", ["subOneAsync"]) }, components: {} }; </script> <style scoped> .sub { border: 1px solid blue; } </style>
add.js
export default { state: { addObj: { name: "add", age: 20 }, addList: [10, 20, 30, 40] }, getters: { aList(state) { return state.addList.filter(item => item > 10); } }, mutations: { addOne(state) { state.addObj.age += 1; }, addN(state, n) { state.addObj.age += n; } }, actions: { addOneAsync(context) { setTimeout(() => { context.commit("addOne"); }, 2000); } }, namespaced: true };
sub.js
export default { state: { subObj: { name: "sub", age: 30 }, subList: [100, 200, 300, 400] }, getters: { sList(state) { return state.subList.filter(item => item > 100); } }, mutations: { subOne(state) { state.subObj.age += 1; }, subN(state, n) { state.subObj.age += n; } }, actions: { subOneAsync(context) { setTimeout(() => { context.commit("subOne"); }, 2000); } }, namespaced: true };
index.js
/* 存放共享数据的仓库 1.导入vue 和 vuex 并注册 2.创建空的仓库 3.导出仓库 4.挂载仓库 */ import Vue from "vue"; import Vuex from "vuex"; import Add from "@/store/modules/add.js"; import Sub from "@/store/modules/sub.js"; Vue.use(Vuex); //这里是全局 const store = new Vuex.Store({ //state状态(共享数据)节点,是一个对象 state: { obj: { name: "张三", age: 18 } }, //mutations节点定义的是方法,这些方法是来修改state中的数据的,只能在mutations中修改 mutations: {}, /*actions节点中,这个节点中放的也是方法,这里面的方法是处理异步业务逻辑的 actions中的方法,参数一是context action不能操作state中的数据,提交的是mutation,mutation修改state中的数据 ---官网描述, action 提交的是mutation,而不是直接变更状态,action可以包含任意异步操作 */ actions: {}, /* getters 基于state中数据派生新的数据 将getters理解组件中的计算属性,写法和计算属性一模一样(计算属性是一个函数,而且必须有返回值return) */ getters: {}, modules: { Add, Sub } //在仓库新增strict节点开启严格模式,辅助开发,但是上线阶段不开启严格模式,开启严格模式后会将state中的数据进行监听 // strict: true, }); export default store;
app.vue
<template> <div id="app"> <h1>add内容区</h1> <hr /> <add-item></add-item> <hr /> <h1>sub内容区</h1> <sub-item></sub-item> </div> </template> <script> import AddItem from "@/components/add-item.vue"; import SubItem from "@/components/sub-item.vue"; export default { name: "app", components: { AddItem, SubItem } }; </script> <style lang="less"></style>
有部分内容可以参考 vuex 之 概念和作用解析