一文完全上手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不陌生了吧,百看不如一练。如果感觉对你有帮助,快收藏起来吧。以上分享仅为自己的见解(不喜勿喷),若有误或者你有更好的方法,欢迎来评论指出
。

浙公网安备 33010602011771号