詳解幾十行代碼實(shí)現(xiàn)一個(gè)vue的狀態(tài)管理
介紹
采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài), 就能實(shí)現(xiàn)組件間數(shù)據(jù)共享
實(shí)現(xiàn)
邏輯圖

從圖上有兩條線(xiàn): Vue.use(vuec), 與 new Vuec.center(options)
第一條線(xiàn)Vue.use(vuec)安裝插件
使用Vue.use(vuec)時(shí), 會(huì)執(zhí)行vuec的install方法,會(huì)注入?yún)?shù)Vue 所以vuec是這樣的,
// index.js
import {Center, install} from './center'
export default {Center, install}
Center對(duì)象將實(shí)例化成center(下面再說(shuō)),我們先看看install方法
// center.js
let Vue // 全局變量, 保存install里的Vue
export function install (_Vue) {
if (!Vue) {
_Vue.mixin({
beforeCreate: applyMixin // 在beforeCreate鉤子上混入applyMixin函數(shù)
})
}
Vue = _Vue
}
install在Vue原型的beforeCreate混入applyMixin函數(shù), 也就是說(shuō)在生成每個(gè)Vue組件時(shí),在它的生命周期beforeCreate鉤子上就會(huì)執(zhí)行applyMixin方法
第二條線(xiàn) new Vuec.center(options)實(shí)例化Center對(duì)象
先看看用戶(hù)傳入的options, 下面例子
export default new Vuec.Center({
state: {
name: 'liuyang'
},
mutations: {
changeName (state) {
state.name = 'jike'
}
}
})
上面代碼會(huì)生成center實(shí)例, 該實(shí)例上應(yīng)該包括:state狀態(tài),commit方法提交變更等
// center.js
export class Center {
constructor (options= {}) {
let center = this
this.mutations = options.mutations
observeState(center, options.state)
}
get state () { // 代理了this.$center.state的最終訪(fǎng)問(wèn)值
return this._vm.$data.$$state
}
commit (_type, _payload) {
this.mutations[_type](this.state, _payload)
}
}
function observeState(center, state) { // 響應(yīng)式state
center._vm = new Vue({
data: {
$$state: state
}
})
}
在執(zhí)行new Vuec.Center({..})時(shí),就是執(zhí)行Center的構(gòu)造函數(shù)
首先執(zhí)行l(wèi)et center = this, 定義center保存當(dāng)前實(shí)例
接著執(zhí)行this.mutations = options.mutations, 在實(shí)例center上添加mutations屬性, 值就是用戶(hù)輸入mutations,
按上面例子, this.mutations長(zhǎng)成這樣
this.mutations = {
changeName (state) {
state.name = 'jike'
}
}
最后執(zhí)行observeState(center, options.state), 作用:讓center實(shí)例的state屬性指向options.state并且是響應(yīng)式的
function observeState(center, state) { // 響應(yīng)式state
center._vm = new Vue({ // 利用Vue的響應(yīng)系統(tǒng),將state轉(zhuǎn)化成響應(yīng)式
data: {
$$state: state
}
})
}
在center實(shí)例上添加_vm屬性, 值是一個(gè)Vue實(shí)例, 在該Vue實(shí)例的data下定義了$$state, 它的值是options.state用戶(hù)輸入的state; 結(jié)合上面的這段代碼
// center.js
export class Center {
...省略
get state () { // 代理了this.$center.state的最終訪(fǎng)問(wèn)值
return this._vm.$data.$$state
}
...省略
}
所以我們?cè)诮M件中訪(fǎng)問(wèn)center.state其實(shí)就是訪(fǎng)問(wèn)center._vm.$data.$$state
OK, center就構(gòu)建好了
創(chuàng)建Vue組件
用戶(hù)輸入
import Vue from 'vue'
import App from './App'
import router from './router'
import center from './center'
new Vue({
el: '#app',
router,
center, // 構(gòu)建好的center實(shí)例
template: '<App/>',
components: {App}
})
在beforeCreate生命周期時(shí)會(huì)觸發(fā)上面混入的applyMixin函數(shù)
// mixins.js
export default function applyMixin() {
vuecInit.call(this) //
}
function vuecInit () {
const options = this.$options
// vue的實(shí)例化是從外往內(nèi), 所以父組件的$center一定是options的center
this.$center = options.parent?options.parent.$center: options.center
}
applyMixin里會(huì)執(zhí)行vuecInit.call(this), 這里的this指向當(dāng)前組件的實(shí)例,
接著看vuecInit, 定義了options等于用戶(hù)輸入選項(xiàng),因?yàn)橄葎?chuàng)建根組件, 所以根組件this.$center的值的引用就是我們?cè)趎ew Vue({..center})時(shí)傳入的center實(shí)例, 下面所有組件都指向它
OK, 你就可以在組件里使用this.$center訪(fǎng)問(wèn)了
commit變更
// center.js
export class Center {
... 省略
commit (_type, _payload) {
this.mutations[_type](this.state, _payload)
}
}
通常我們變更時(shí): this.$center.commit('changeName', 'jike'), 這樣的話(huà), this.mutations[_type]就是對(duì)應(yīng)方法函數(shù), 往該函數(shù)里傳入state以及payload,
舉上面的例子
// this.mutations[_type] , _type = 'changeName', payload= 'jike'
this.mutations = {
changeName (state, payload) {
state.name = payload
}
}
說(shuō)明
上面只是一個(gè)簡(jiǎn)單的狀態(tài)管理, 還有很多地方?jīng)]有實(shí)現(xiàn): actions異步變更,getters函數(shù),modules模塊分割, 輔助函數(shù)mapState..等
源碼地址: github
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue3?+?async-validator實(shí)現(xiàn)表單驗(yàn)證的示例代碼
表單驗(yàn)證可以有效的過(guò)濾不合格的數(shù)據(jù),減少服務(wù)器的開(kāi)銷(xiāo),并提升用戶(hù)的使用體驗(yàn),今天我們使用?vue3?來(lái)做一個(gè)表單驗(yàn)證的例子,需要的朋友跟隨小編一起學(xué)習(xí)下吧2022-06-06
vue項(xiàng)目之index.html如何引入JS文件
這篇文章主要介紹了vue項(xiàng)目之index.html如何引入JS文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
VUE如何實(shí)現(xiàn)點(diǎn)擊文字添加顏色(動(dòng)態(tài)修改class)
這篇文章主要介紹了VUE如何實(shí)現(xiàn)點(diǎn)擊文字添加顏色(動(dòng)態(tài)修改class),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
vue2實(shí)現(xiàn)無(wú)感刷新token的方式詳解
在Web應(yīng)用中,用戶(hù)需要通過(guò)認(rèn)證和授權(quán)才能訪(fǎng)問(wèn)受保護(hù)的資源,為了實(shí)現(xiàn)認(rèn)證和授權(quán)功能,通常需要使用Token來(lái)標(biāo)識(shí)用戶(hù)身份并驗(yàn)證其權(quán)限,本文給大家介紹了vue2實(shí)現(xiàn)無(wú)感刷新token的方式,需要的朋友可以參考下2024-02-02
淺談vue websocket nodeJS 進(jìn)行實(shí)時(shí)通信踩到的坑
這篇文章主要介紹了淺談vue websocket nodeJS 進(jìn)行實(shí)時(shí)通信踩到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
詳解在vue-cli項(xiàng)目中使用mockjs(請(qǐng)求數(shù)據(jù)刪除數(shù)據(jù))
本篇文章主要介紹了在vue-cli項(xiàng)目中使用mockjs(請(qǐng)求數(shù)據(jù)刪除數(shù)據(jù)),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
vue3?element-plus?實(shí)現(xiàn)表格數(shù)據(jù)更改功能詳細(xì)步驟
這篇文章主要介紹了vue3 element-plus實(shí)現(xiàn)表格數(shù)據(jù)更改功能,本文分步驟結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
vue如何監(jiān)聽(tīng)頁(yè)面的滾動(dòng)的開(kāi)始和結(jié)束
這篇文章主要介紹了vue如何監(jiān)聽(tīng)頁(yè)面的滾動(dòng)的開(kāi)始和結(jié)束,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07

