持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
前言
大家好,不知道大家在用vue进行开发过程中有没有遇到这样一种场景,就是有些时候一些数据是一种通用的共享数据(比如登录信息),那么这类数据在各个组件模块中可能都会用到,如果每个组件中都去后台重新获取那么势必会造成性能浪费,为了解决这一问题一个新的状态管理工具 - vux就应运而生了。那么vuex到底是个什么东西呢,它又是怎么实现数据共享的呢?接下来就跟大家共同学习一下。
了解vuex
官方给出的解释是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。其实可以简单理解为:将多个组件共享的变量全部存储在一个对象里面,然后将这个对象放在顶层的 Vue 实例中,让其他组件可以使用,它最大的特点是响应式。
vuex有如下五个核心模块:
state
- 用于存放组件间互相通信的属性值。
- 原则上state中的属性只能在各个组件之间使用,而不能修改,如果要修改需要在mutations中修改
//伪代码
//定义
export default new Vuex.Store({
state:{
userinfo:{name:'Alvin'}
}
})
//使用
this.$store.state.userinfo.name
mutations
- 这里存放的都是一些函数,用于修改state中的属性值
- 这里的函数中只接收两个参数:state和options
- 原则上这里面的函数必须都是同步的
- 如果某组件中需要修改state中的属性值,则需在该组件中用this.$store.commit('方法名', 参数)的方式来调用,即需要用commit方法来调用mutations中的函数
- 通过commit触发
//伪代码
//定义
export default new Vuex.Store({
mutations:{
changeUserInfo(state,name){
state.userinfo.name = name;
}
}
})
//使用
this.$store.commit("changeUserInfo", "Yannis")
actions
- 这里存放的也都是一些函数,这里的函数可以是异步的
- 这里的函数也是接收两个参数:store和options
- 如果这里的函数想要修改state中的值,还是得通过调用mutations中的方法来实现
- 如果想要在组件中调用这里的函数,则需要用dispatch方法调用:this.$store.dispatch('方法名', options)
- 通过dispatch触发
getters
- 这里也是一些函数,类似于组件中的计算属性
- 可以处理一些通用且复杂的逻辑, 实际使用比较少
modules
- 用于划分模块
- 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象显得会相当臃肿
- 为了解决上面的问题,Vuex允许将store分割成模块。每个模块拥有自己的state、mutation、action、getter甚至是嵌套子模块
- 如果模块中的mutations或actions重复,则两个重复的方法都会执行
- 如果想区分模块中重复的mutations或actions,则可以在模块中加一个属性:namespace:true即可,调用时需要指定模块名,例如:this.$store.commit('模块名/方法名')
基于vuex的原理模拟部分Vuex源码
let Vue = null;
function install(_Vue){
Vue = _Vue;
Vue.mixin({
beforeCreate(){
if(this.$options.store){
//说明是根实例
this$store = this.$options.$store
}else if(this.$parent){
//有$parent属性,说明这个组件是根组件的后代组件
this.$store = this.$parent.$store
}
}
});
}
class Store{
constructor(options){
//this.state = options.state;//没有响应式
let vm = new Vue({
data:{
state: options.state
}
});
this.state = vm.state;
this.mutations = {};
let mutations = options.mutations || {};
Object.keys(mutations).forEach(key => {
this.mutations[key] = (option) => {
mutations[key].call(this,this.state, option);
}
});
this.actions = {};
let actions = options.actions || {};
Object.keys(actions).forEach(key => {
this.actions[key] = (option) => {
actions[key].call(this, this.store, option);
}
});
this.getters = {};
let getters = options.getters || {};
Object.keys(getters ).forEach(key => {
Object.defineProperty(this.getters, key, {
get:() => {
return getters[key].call(this, this.state);
}
})
});
this.commit = (type, option) => {
this.mutations[type](option);
}
this.dispatch = (type, option) => {
this.actions[type](option);
}
}
/*
* commit 和 dispatch应该是stote私有的
commit(type, option){
this.mutations[type](option );
}
dispatch(type, option){
this.actions[type](option);
}
*/
}
//辅助函数
export function mapState(arr){
let obj = {};
arr.forEach(key => {
obj[key] = function(){
return this.$store.state[key]
}
});
return obj;
}
export function mapMutation(arr){
let obj = {};
arr.forEach(key => {
obj[key] = function(option){
return this.$store.commit(key, option)
}
});
return obj;
}
export default {
install,
Store
}
总结
本次分享中我们共同学习了vue中的状态管理模式 - vuex,最后还用重写vuex的方式简单梳理了一下vuex的实现过程,关于具体的实现原理我们会在以后的分享中详细描述。今天的分享就到这里了。