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

從圖上有兩條線: Vue.use(vuec), 與 new Vuec.center(options)
第一條線Vue.use(vuec)安裝插件
使用Vue.use(vuec)時, 會執(zhí)行vuec的install方法,會注入?yún)?shù)Vue 所以vuec是這樣的,
// index.js
import {Center, install} from './center'
export default {Center, install}
Center對象將實例化成center(下面再說),我們先看看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ù), 也就是說在生成每個Vue組件時,在它的生命周期beforeCreate鉤子上就會執(zhí)行applyMixin方法
第二條線 new Vuec.center(options)實例化Center對象
先看看用戶傳入的options, 下面例子
export default new Vuec.Center({
state: {
name: 'liuyang'
},
mutations: {
changeName (state) {
state.name = 'jike'
}
}
})
上面代碼會生成center實例, 該實例上應該包括: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的最終訪問值
return this._vm.$data.$$state
}
commit (_type, _payload) {
this.mutations[_type](this.state, _payload)
}
}
function observeState(center, state) { // 響應式state
center._vm = new Vue({
data: {
$$state: state
}
})
}
在執(zhí)行new Vuec.Center({..})時,就是執(zhí)行Center的構造函數(shù)
首先執(zhí)行l(wèi)et center = this, 定義center保存當前實例
接著執(zhí)行this.mutations = options.mutations, 在實例center上添加mutations屬性, 值就是用戶輸入mutations,
按上面例子, this.mutations長成這樣
this.mutations = {
changeName (state) {
state.name = 'jike'
}
}
最后執(zhí)行observeState(center, options.state), 作用:讓center實例的state屬性指向options.state并且是響應式的
function observeState(center, state) { // 響應式state
center._vm = new Vue({ // 利用Vue的響應系統(tǒng),將state轉化成響應式
data: {
$$state: state
}
})
}
在center實例上添加_vm屬性, 值是一個Vue實例, 在該Vue實例的data下定義了$$state, 它的值是options.state用戶輸入的state; 結合上面的這段代碼
// center.js
export class Center {
...省略
get state () { // 代理了this.$center.state的最終訪問值
return this._vm.$data.$$state
}
...省略
}
所以我們在組件中訪問center.state其實就是訪問center._vm.$data.$$state
OK, center就構建好了
創(chuàng)建Vue組件
用戶輸入
import Vue from 'vue'
import App from './App'
import router from './router'
import center from './center'
new Vue({
el: '#app',
router,
center, // 構建好的center實例
template: '<App/>',
components: {App}
})
在beforeCreate生命周期時會觸發(fā)上面混入的applyMixin函數(shù)
// mixins.js
export default function applyMixin() {
vuecInit.call(this) //
}
function vuecInit () {
const options = this.$options
// vue的實例化是從外往內, 所以父組件的$center一定是options的center
this.$center = options.parent?options.parent.$center: options.center
}
applyMixin里會執(zhí)行vuecInit.call(this), 這里的this指向當前組件的實例,
接著看vuecInit, 定義了options等于用戶輸入選項,因為先創(chuàng)建根組件, 所以根組件this.$center的值的引用就是我們在new Vue({..center})時傳入的center實例, 下面所有組件都指向它
OK, 你就可以在組件里使用this.$center訪問了
commit變更
// center.js
export class Center {
... 省略
commit (_type, _payload) {
this.mutations[_type](this.state, _payload)
}
}
通常我們變更時: this.$center.commit('changeName', 'jike'), 這樣的話, this.mutations[_type]就是對應方法函數(shù), 往該函數(shù)里傳入state以及payload,
舉上面的例子
// this.mutations[_type] , _type = 'changeName', payload= 'jike'
this.mutations = {
changeName (state, payload) {
state.name = payload
}
}
說明
上面只是一個簡單的狀態(tài)管理, 還有很多地方?jīng)]有實現(xiàn): actions異步變更,getters函數(shù),modules模塊分割, 輔助函數(shù)mapState..等
源碼地址: github
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Vue使用babel-polyfill兼容IE解決白屏及語法報錯問題
這篇文章主要介紹了Vue使用babel-polyfill兼容IE解決白屏及語法報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
vue draggable resizable 實現(xiàn)可拖拽縮放的組件功能
這篇文章主要介紹了vue draggable resizable 實現(xiàn)可拖拽縮放的組件功能,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07
vue前端實現(xiàn)導出頁面為pdf(分頁導出、不分頁導出及分模塊導出)
在實際應用中可能用戶希望將系統(tǒng)中一個頁面展示的所有數(shù)據(jù)報表,用PDF的文件格式下載下來,以便于其他用途,這篇文章主要給大家介紹了關于vue前端實現(xiàn)導出頁面為pdf(分頁導出、不分頁導出及分模塊導出)的相關資料,需要的朋友可以參考下2024-06-06
vue監(jiān)聽瀏覽器網(wǎng)頁關閉和網(wǎng)頁刷新事件代碼示例
在前端開發(fā)中我們通常會遇到這樣的需求,用戶離開、刷新頁面前,修改數(shù)據(jù)未進行保存操作,需要提示框提醒用戶,這篇文章主要給大家介紹了關于vue監(jiān)聽瀏覽器網(wǎng)頁關閉和網(wǎng)頁刷新事件的相關資料,需要的朋友可以參考下2023-08-08

