实现一个简单的vuex
上篇文章 我们实现了一个简单的vue-router,这一篇 我们趁热打铁 实现一个简单的vuex
通过vuex的官网 我们知道vuex的作用
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
关键词 集中式 状态 可预测
使用方法
import Vue from 'vue'
import Vuex from '../utils/gvuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:1,
name:"gaojian"
},
mutations: {
add(state,payload){
state.count =state.count+payload
},
changename(state,payload){
state.name =state.name+payload
}
},
actions: {
add({commit},payload){
setTimeout(()=>{
commit("add",payload)
},2000)
}
},
modules: {
}
})
使用
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
分析
Vue.use(Vuex) 说明暴露出来了一个install方法
new Vuex.Store()说明了暴露出来了一个store对象
所以应该
function install(_vue, options) {
Vue = _vue;
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
//暴露一个全局的$store
Vue.prototype.$store = this.$options.store
}
},
})
}
export default {
Store,
install
}
1.data数据变化要改变视图,所以数据需要是响应式的;
先处理直接提叫mutation的情况
let Vue
class Store {
constructor(options) {
this._mutation = options.mutations;
this.vm = new Vue({
data: {
state: options.state
},
})
this.state = this.vm.state
}
commit(type, payload) {
if (this._mutation[type]) {
this._mutation[type](this.state, payload)
}
}
}
调用
changeName(){
this.$store.commit('changename',2)
}
2.处理dispatch的情况 (注意commit时候this的指向问题,需要绑定一下)
class Store {
constructor(options) {
this._mutation = options.mutations;
this._actions = options.actions;
this.vm = new Vue({
data: {
state: options.state
},
})
this.state = this.vm.state
this.commit = this.commit.bind(this)
}
commit(type, payload) {
if (this._mutation[type]) {
this._mutation[type](this.state, payload)
}
}
dispatch(type, payload) {
if (this._actions[type]) {
this._actions[type](this, payload)
}
}
}
3.处理getters的情况 getter是需要依赖 vue的comnputed属性;
注意点:
借助vue的comnputed属性需要将由参的函数转化成没有参数的函数
getters:{
doubleCount:(state)=>{
return state.count*2
},
threeCount:(state)=>{
return state.count*3
}
},
// 类似于
computed:{
doubleCount(){
return state.count*2
},
}
class Store {
constructor(options) {
this._mutation = options.mutations;
this._actions = options.actions;
this._wrapgetters = options.getters;
let computed = {};
this.getters = {};
let store = this
Object.keys(this._wrapgetters).forEach((key) => {
let fn = store._wrapgetters[key];
computed[key] = function(){
return fn(store.state)
}
Object.defineProperty(store.getters,
key,
{
get: () => {
console.log(this._wrapgetters[key](store.state),333);
// return store.vm[key]
return this._wrapgetters[key](store.state)
}
}
)
})
this.vm = new Vue({
data: {
state: options.state
},
computed
})
this.state = this.vm.state
this.commit = this.commit.bind(this)
}
commit(type, payload) {
if (this._mutation[type]) {
this._mutation[type](this.state, payload)
}
}
dispatch(type, payload) {
if (this._actions[type]) {
this._actions[type](this, payload)
}
}
}
完整版代码
let Vue
class Store {
constructor(options) {
this._mutation = options.mutations;
this._actions = options.actions;
this._wrapgetters = options.getters;
let computed = {};
this.getters = {};
let store = this
Object.keys(this._wrapgetters).forEach((key) => {
let fn = store._wrapgetters[key];
computed[key] = function(){
return fn(store.state)
}
Object.defineProperty(store.getters,
key,
{
get: () => {
console.log(this._wrapgetters[key](store.state),333);
return store.vm[key]
}
}
)
})
this.vm = new Vue({
data: {
state: options.state
},
computed
})
this.state = this.vm.state
this.commit = this.commit.bind(this)
}
commit(type, payload) {
if (this._mutation[type]) {
this._mutation[type](this.state, payload)
}
}
dispatch(type, payload) {
if (this._actions[type]) {
this._actions[type](this, payload)
}
}
}
function install(_vue, options) {
Vue = _vue;
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
},
})
}
export default {
Store,
install
}