实现一个简单的vuex
Posted mengyuhang4879
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现一个简单的vuex相关的知识,希望对你有一定的参考价值。
vuex的用法
<div id="app">
弟弟的年龄:{{$store.state.age}}
哥哥的年龄:{{$store.getters.getAge}}
<button @click="$store.commit(\'changeAge\',5)">五年后</button>
<button @click="$store.dispatch(\'changeAge\',10)">十年后</button>
</div>
store
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
//状态
state: {
age: 18
},
//相当于计算属性
getters: {
getAge(state) {
return state.age + 10;
}
},
//修改状态的方法
mutations: {
changeAge(state, payload) {
state.age = state.age + payload;
}
},
//解决mutations只有同步没有异步
actions: {
changeAge({ commit }, payload) {
setTimeout(() => {
commit("changeAge", payload);
},1000);
}
}
});
main
import store from "./store";
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
简单的实现
vuex/index
vuex/index
作为总出口 使用两种形式导出
export {} ===> import {Store} from \'vuex\'
export default ===> import Store from \'vuex\'
import { Store, install } from "./store";
export { Store, install };
export default {
Store,
install,
};
vuex/store
vuex/store.js
这个文件为了方便将install方法和Store类写在一起
install
install方法:将new Vue({store}) 中的store利用Vue的minxin方法通过递归遍历使所有组件都可以用$store来获取到
let Vue;
export const install = (_Vue) => {
Vue = _Vue;
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
this.$store = this.$options.store;
} else if (this.$options.parent && this.$options.parent.$options.store) {
this.$store = this.$options.parent.$options.store;
}
},
});
};
Store
state 方法
实现了install方法之后我们发现这样实现state更为方便一些
export class Store {
constructor(options) {
this.state = options.state
}
}
上面这种可以获取到 但是并没有将state进行双向数据绑定,state改变视图并不会发生改变,上面的install方法可以拿到全局的Vue,这样我们可以利用Vue中的observe来将state中的数据添加get和set方法
export class Store {
constructor(options) {
let state = options.state;
this._vm = new Vue({
data: {
//$$为内部方法 不挂载在实例上
$$state: state,
},
});
}
//取state这个值得时候会触发这个方法
get state() {
return this._vm._data.$$state;
}
}
公共方法forEach的实现
export const forEach = (obj, fn) => {
Object.keys(obj).forEach((v) => fn(v, obj[v]));
};
使用方法
forEach({ name: "孟", val: "01" }, (key, fn) => {
console.log(key, fn);
});
//传入一个对象,获取到对象的每一个key和val
getters方法的实现
getters
是一个对象 使用的时候$store.getters.getAge
,是getAge执行后的结果
this.getters = {};
let computed = {};
forEach(options.getters, (key, fn) => {
//每次其他数据变化刷新页面都会进行没必要的获取getters中的数据,computed具有缓存的效果 数据不发生改变就不会触发相应的方法
computed[key] = () => {
return fn(this.state);
};
//给getter进行双向数据绑定
Object.defineProperty(this.getters, key, {
//computed是挂载在实例上的属性
get: () => this._vm[key],
});
});
this._vm = new Vue({
data: {
$$state: state,
},
computed,
});
mutations实现
mutations是依据发布订阅模式先将每一个函数储存在事件池中,然后通过用户的一个派发动作使对应的事件池中的函数执行
class Store {
constructor(options) {
this.mutations = {};
forEach(options.mutations, (key, fn) => {
this.mutations[key] = (payload) => fn(this.state,payload);
});
}
commit = (key, payload) => {
this.mutations[key](payload);
};
}
actions的实现
class Store {
constructor(options) {
this.actions = {};
forEach(options.actions, (key, fn) => {
this.actions[key] = (payload) => fn(this, payload);
});
dispatch = (key, payload) => {
this.actions[key](payload);
};
}
以上是关于实现一个简单的vuex的主要内容,如果未能解决你的问题,请参考以下文章