Vuex
provide和inject虽然能够实现层层传递的数据管理,但对于一个大的管理系统而言会显得有些繁琐,我们需要一个大型的状态管理系统。
如何使用
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
Vue.use(Vuex)
Vue.config.productionTip = false
const store = new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
increment({commit}) {
setTimeout(()=>{
// state.count++ // 不要对state进行更改操作,应该通过commit交给mutations去处理
commit('increment')
}, 3000)
}
},
getters: {
doubleCount(state) {
return state.count * 2
}
}
})
new Vue({
store,
render: h => h(App),
}).$mount('#app')
APP.vue中,?$store.dispatch 对应的是action 的定义,$store.commit 对应的是mutations ?的定义:
<template>
<div id="app">
{{count}}
<br>
{{$store.getters.doubleCount}}
<button @click="$store.commit('increment')">count++</button>
<button @click="$store.dispatch('increment')">count++</button>
</div>
</template>
<script>
export default {
name: 'app',
computed: {
count() {
return this.$store.state.count
}
}
}
</script>
<style>
</style>
$store 是如何是如何挂载到实例 this 上的? 通过new Vue中放置store
Vuex的核心概念和底层原理
?
?min-vuex实例:一个简单的min-vuex:
import Vue from 'vue'
const Store = function Store (options = {}) {
const {state = {}, mutations={}} = options
this._vm = new Vue({
data: {
$$state: state
},
})
this._mutations = mutations
}
Store.prototype.commit = function(type, payload){
if(this._mutations[type]) {
this._mutations[type](this.state, payload)
}
}
Object.defineProperties(Store.prototype, {
state: {
get: function(){
return this._vm._data.$$state
}
}
});
export default {Store}
在这个简易的min-vuex中,我们定义了state、mutation、commit、get等属性,可以将上述的case中的vuex替换为我们的min-vuex,计时器也是可以跑起来的。 main.js文件
import Vue from 'vue'
import Vuex from './min-vuex'
import App from './App.vue'
Vue.use(Vuex)
Vue.config.productionTip = false
const store = new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
}
},
// actions: {
// increment({commit}) {
// setTimeout(()=>{
// // state.count++ // 不要对state进行更改操作,应该通过commit交给mutations去处理
// commit('increment')
// }, 3000)
// }
// },
// getters: {
// doubleCount(state) {
// return state.count * 2
// }
// }
})
Vue.prototype.$store = store
new Vue({
// store,
render: h => h(App),
}).$mount('#app')
App.vue文件
<template>
<div id="app">
{{count}}
<button @click="$store.commit('increment')">count++</button>
</div>
</template>
<script>
export default {
name: 'app',
computed: {
count() {
return this.$store.state.count
}
}
}
</script>
<style>
</style>
扩展简化版的 min-vuex,实现 getters,并实现 Vuex 的方式注入$store
- 计算属性computer实现getters缓存
- beforeCreate中混入$store的获取方式
看一下扩展后的min-vuex let Vue;
function install (_Vue) {
Vue = _Vue;
function vuexInit () {
var options = this.$options;
// store injection
if (options.store) {
this.$store = typeof options.store === 'function'
? options.store()
: options.store;
} else if (options.parent && options.parent.$store) {
this.$store = options.parent.$store;
}
}
Vue.mixin({ beforeCreate: vuexInit });
}
const Store = function Store (options = {}) {
const {state = {}, mutations={}, getters={}} = options
const computed = {}
const store = this
store.getters = {};
for (let [key, fn] of Object.entries(getters)) {
computed[key] = function () { return fn(store.state, store.getters); };
Object.defineProperty(store.getters, key, {
get: function () { return store._vm[key]; },
});
}
this._vm = new Vue({
data: {
$$state: state
},
computed,
})
this._mutations = mutations
}
Store.prototype.commit = function(type, payload){
if(this._mutations[type]) {
this._mutations[type](this.state, payload)
}
}
Object.defineProperties(Store.prototype, {
state: {
get: function(){
return this._vm._data.$$state
}
}
});
export default {Store, install}
|