一文完全上手vuex
大佬手摸手教你写vuex
https://zhuanlan.zhihu.com/p/464492572
1
Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。什么情景下使用呢?多个视图公用状态的时候,紧靠父子传参是比较麻烦的,特别是嵌套的组件较多的时候。这样用vuex就很方便的把数据共享出来了。
总结一下
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
在页面中使用vuex一共有四个展开函数,可以分别把state、getters、mutattions,actions展开使在页面中更方便的调用,而不需要this.$store.xxx,直接在页面中xxx就行了
其中推荐把:
mapState、mapGeters写在计算属性computed中 ...mapState(['展开的属性一'],['展开的属性二']...) ...mapGetters(['展开的属性一'],['展开的属性二']...)
mapMutations, mapActions 写在函数中 ...
mapMutations
(['展开的方法一'],['展开的方法二']...)
...
mapActions
(['展开的方法一'],['展开的方法二']...)
2 安装 npm install vuex --save 3 导入 在src文件夹下创建store文件夹,在里面创建一个index.js文件。 import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); 4 创建状态管理对象store state对象里面是定义的状态(数据) export default new Vuex.Store({ state: { //定义数据 person: { name: "张三", age: 15, }, } }); 5 注册到vue(main.js) import Vue from "vue"; import App from "./App.vue"; import store from "./store";//引入我们前面导出的store对象 Vue.config.productionTip = false; new Vue({ store,//把store对象添加到vue实例上 render: (h) => h(App), }).$mount("#app"); 6 如何使用(App.vue) 了解State <template> <div id="app"> <div>人名:{{ $store.state.person.name }}</div> <div>年龄:{{ $store.state.person.age }}</div> </div> </template> <script> export default { name: "App", components: {}, methods: { }, }; </script> <style> </style> 运行效果: 官方建议1: 官方建议我们以上操作this.$http://store.state.XXX最好放在计算属性中,当然,我也建议你这么使用,这样可以让你的代码看起来更优雅一些,就像这样: <template> <div id="app"> <div>人名:{{ getPerson.name }}</div> <div>年龄:{{ getPerson.age }}</div> </div> </template> <script> export default { name: "App", components: {}, methods: {}, computed: { getPerson() { return this.$store.state.person; }, }, }; </script> <style> </style> 和上面的运行效果是一样的。 官方建议2: 是不是每次都写this.$http://store.state.XXX让你感到厌烦,你实在不想写这个东西怎么办,当然有解决方案,就像下面这样: <template> <div id="app"> <div>人名:{{ person.name }}</div> <div>年龄:{{ person.age }}</div> </div> </template> <script> import { mapState } from "vuex"; // 从vuex中导入mapState export default { name: "App", components: {}, methods: {}, computed: { ...mapState(["person"])// 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它 } }; </script> <style> </style> 如果解构的时候,想改属性的名字,那么你可以这样写: computed: { ...mapState({ personNew: "person" })//注意这里展开的是对象,不是数组 } 看到现在为止,你已经可以在任何组件中来操作状态了 了解Getter 接下来该Getter方法闪亮登场了,Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。 简单来说就是可以对你的state数据进行修饰,比如上述例子中的人名已经渲染出来了,现在要求用符号把人名包裹起来。 import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: { //定义数据 person: { name: "张三", age: 15 } }, getters: { getName(state) { //该方法可以接收2个参数,1.state对象 2.getters对象 return `【${state.person.name}】`; } } }); 在组件中使用 <template> <div id="app"> <div>人名:{{ $store.getters.getName }}</div> <div>年龄:{{ person.age }}</div> <button @click="updatePerson">修改个人信息</button> </div> </template> <script> import { mapState } from "vuex"; // 从vuex中导入mapState export default { name: "App", components: {}, methods: {} }, mounted() {}, computed: { ...mapState(["person"]) // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它 } }; </script> <style> </style> 运行效果: 官方建议: 如果你觉得每次都要写 $http://store.getters.xxx比较麻烦,我们可以使用mapGetters去解构到计算属性中,此时就可以直接像访问计算属性一样访问它。 <template> <div id="app"> <div>人名:{{ getName }}</div> <div>年龄:{{ person.age }}</div> <button @click="updatePerson">修改个人信息</button> </div> </template> <script> import { mapState, mapGetters } from "vuex"; // 从vuex中导入mapState export default { name: "App", components: {}, methods: {}, computed: { ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它 ...mapGetters(["getName"]) } }; </script> <style> </style> 此时查看运行的效果是一样的,你也可以给这个属性换个名字。 ...mapGetters({ aliasName: 'getName' }), // 赋别名的话,这里接收对象,而不是数组 Mutation 接下来介绍一下修改状态值的方法:Mutation 说到这里有人会想到this.$http://store.state.XXX = XXX;(切记:这是错误的写法) 1.更改 Vuex 的 store 中的状态的唯一方法是提交 mutation 2.mutations里面的函数必须是同步操作,不能是异步(后面会介绍如何用异步操作) 看例子我要点击按钮的时候,修改信息。 import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: { //定义数据 person: { name: "张三", age: 15 } }, getters: { getName(state) { //该方法可以接收2个参数,1.state对象 2.getters对象 return `【${state.person.name}】`; } }, mutations: { //定义修改状态的方法 updatePerson(state, val) { //该方法可以接收2个参数,1.state对象 2.val传进来要更新的值 state.person = val; } } }); 组件中调用 <template> <div id="app"> <div>人名:{{ getName }}</div> <div>年龄:{{ person.age }}</div> <button @click="updatePerson">修改个人信息</button> </div> </template> <script> import { mapState, mapGetters } from "vuex"; // 从vuex中导入mapState export default { name: "App", components: {}, methods: { updatePerson() { this.$store.commit("updatePerson", { name: "李四", age: 25 }); } }, mounted() {}, computed: { ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它 ...mapGetters(["getName"]) } }; </script> <style> </style> 运行效果: 点击修改个人信息按钮前: 点击修改个人信息按钮后: 官方建议: 是不是感觉写this.$store.commit('XXX')比较麻烦呢,我们可以使用mapMutations去解构到方法中,此时就可以直接像调用函数一样去使用它。 <template> <div id="app"> <div>人名:{{ getName }}</div> <div>年龄:{{ person.age }}</div> <button @click="updatePerson({name: '李四', age: 25})">修改个人信息</button> </div> </template> <script> import { mapState, mapGetters, mapMutations } from "vuex"; // 从vuex中导入mapState export default { name: "App", components: {}, methods: { ...mapMutations(["updatePerson"]) // updatePerson() { // this.$store.commit("updatePerson", { name: "李四", age: 25 }); // } }, mounted() {}, computed: { ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它 ...mapGetters(["getName"]) } }; </script> <style> </style> 此时可以得到和之前一样的效果,当然你也可以给它换个名字。 methods:{ ...mapMutations({ updatePersonNew: 'updatePerson' }), // 赋别名的话,这里接收对象,而不是数组 } Action 接下来我们来了解下Action,可以存放异步操作。 Action类似于mutation,不同的是: 1.Action 提交的是 mutation,而不是直接变更状态。前面也提到过mutation是唯一可修改状态的方法。 2.Action可以包含任意异步操作 import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: { //定义数据 person: { name: "张三", age: 15 } }, getters: { getName(state) { //该方法可以接收2个参数,1.state对象 2.getters对象 return `【${state.person.name}】`; } }, mutations: { //定义修改状态的方法 updatePerson(state, val) { //该方法可以接收2个参数,1.state对象 2.val传进来要更新的值 state.person = val; }, setName(state, name) { state.person.name = name; } }, actions: { setN(content) { // 增加setN方法,默认第一个参数是content,其值是复制的一份store return new Promise(resolve => { // 我们模拟一个异步操作,1秒后修改人名为action王五 setTimeout(() => { content.commit("setName", "action王五"); resolve(); }, 1000); }); } } }); 组件中调用: <template> <div id="app"> <div>人名:{{ getName }}</div> <div>年龄:{{ person.age }}</div> <button @click="$store.dispatch('setN');">修改个人信息</button> </div> </template> <script> import { mapState, mapGetters, mapMutations } from "vuex"; // 从vuex中导入mapState export default { name: "App", components: {}, methods: { ...mapMutations(["updatePerson"]) }, mounted() {}, computed: { ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它 ...mapGetters(["getName"]) } }; </script> <style> </style> 运行效果:点击按钮1秒后。 看到这里知道我要说什么了吧,哈哈哈... 官方建议1: 是不是感觉写$store.dispatch('xxx')比较麻烦呢,我们可以使用mapActions去解构到方法中,此时就可以直接像调用函数一样去使用它。 <template> <div id="app"> <div>人名:{{ getName }}</div> <div>年龄:{{ person.age }}</div> <button @click="setN">修改个人信息</button> </div> </template> <script> import { mapState, mapGetters, mapMutations, mapActions } from "vuex"; // 从vuex中导入mapState export default { name: "App", components: {}, methods: { ...mapMutations(["updatePerson"]), ...mapActions(["setN"]) }, mounted() {}, computed: { ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它 ...mapGetters(["getName"]) } }; </script> <style> </style> 运行效果是一样的,当然你也可以给它起一个别名。 ...mapActions({ setName: 'setN' }), // 赋别名的话,这里接收对象,而不是数组 官方建议2: actions里面方法的形参可以直接将commit解构出来,这样可以更方便的去使用。 actions: { setN({ commit }) { // 增加setN方法,默认第一个参数是content,其值是复制的一份store return new Promise(resolve => { // 我们模拟一个异步操作,1秒后修改人名为action王五 setTimeout(() => { commit("setName", "action王五"); resolve(); }, 1000); }); } } 总结:看到这里你应该对vuex不陌生了吧,百看不如一练。如果感觉对你有帮助,快收藏起来吧。以上分享仅为自己的见解(不喜勿喷),若有误或者你有更好的方法,欢迎来评论指出 。