面試官:說(shuō)下 vuex 實(shí)現(xiàn)原理?
Vuex 是 Vue.js 專用的狀態(tài)管理模式和庫(kù),統(tǒng)一管理應(yīng)用的全局狀態(tài),解決組件之間的數(shù)據(jù)共享問(wèn)題。其本質(zhì)原理是利用 Vue 提供的響應(yīng)式系統(tǒng),配合 Vue 的數(shù)據(jù)響應(yīng)機(jī)制實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)視圖更新。
一、Vuex 設(shè)計(jì)核心(五大核心模塊)
Vuex主要包括如下幾個(gè)模塊:
模塊 | 功能 | 是否響應(yīng)式 |
State | 存儲(chǔ)全局狀態(tài)的數(shù)據(jù)對(duì)象 | ? |
Getters | 對(duì) State 數(shù)據(jù)進(jìn)行加工處理,類似組件內(nèi)的 computed 計(jì)算屬性 | ? |
Mutations | 同步修改 State 數(shù)據(jù)的唯一方法,觸發(fā)響應(yīng)式更新 | ?(只是觸發(fā)更新,不必響應(yīng)式) |
Actions | 提交 Mutations,可以包含異步邏輯 | ? |
Modules | 分模塊管理狀態(tài),方便擴(kuò)展與維護(hù) | ? |
二、vuex 的實(shí)現(xiàn)原理(詳細(xì)拆解)
① Vue 響應(yīng)式基礎(chǔ)
Vuex 最根本的原理是基于 Vue 本身的數(shù)據(jù)響應(yīng)系統(tǒng):
- 通過(guò) new Vue() 或 Vue.observable 方法: 將 state 對(duì)象定義為 Vue 實(shí)例的 data 屬性或通過(guò) Vue.observable 變成響應(yīng)式。
// 簡(jiǎn)單的響應(yīng)式 state 實(shí)現(xiàn)示例
let state = Vue.observable({ count: 0 });
- 當(dāng) state 數(shù)據(jù)變化時(shí),任何使用 state 數(shù)據(jù)的組件都會(huì)自動(dòng)響應(yīng)式更新。
② 核心實(shí)現(xiàn)——store 對(duì)象
- store 是一個(gè)單例對(duì)象,整個(gè)應(yīng)用僅有一個(gè)。
- store 實(shí)例包含 State、Getters、Mutations、Actions 等成員。
核心示意代碼:
class Store {
constructor(options) {
this._vm = new Vue({
data: {
$$state: options.state
}
});
this.getters = {};
Object.keys(options.getters || {}).forEach(getterName => {
Object.defineProperty(this.getters, getterName, {
get: () => options.getters[getterName](this.state)
});
});
this.mutations = options.mutations || {};
this.actions = options.actions || {};
}
// 提供 state 訪問(wèn)方式
get state() {
return this._vm._data.$$state;
}
// mutation必須同步執(zhí)行
commit = (type, payload) => {
const mutation = this.mutations[type];
if (mutation) mutation(this.state, payload);
else console.error(`[vuex] unknown mutation type: ${type}`);
};
// action 可以異步
dispatch = (type, payload) => {
const action = this.actions[type];
if (action) return action(this, payload);
else console.error(`[vuex] unknown action type: ${type}`);
};
}
③ Vuex 的輔助函數(shù)(輔助方法)
- 輔助函數(shù) mapState、mapGetters、mapMutations、mapActions,方便組件使用 store 中的數(shù)據(jù)與方法。
示例:
// vue組件內(nèi)使用vuex的輔助函數(shù)示例
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
export default {
computed: {
...mapState(['count']),
...mapGetters(['doubleCount'])
},
methods: {
...mapMutations(['increment']),
...mapActions(['incrementAsync'])
}
};
④ 嚴(yán)格模式(strict mode)
嚴(yán)格模式下,只能通過(guò) mutation 修改 state,防止不規(guī)范的 state 修改行為:
const store = new Vuex.Store({
strict: true
});
嚴(yán)格模式原理是使用 Vue 提供的 watch API 監(jiān)聽 state 變化,判斷 state 變化是否是 mutation 導(dǎo)致的。如果不是,會(huì)給出警告。
三、vuex 流程示意圖(核心實(shí)現(xiàn)流程圖示)
Vue組件
│
dispatch (異步) → Actions ──commit──→ Mutations
│ │
└─────────→ commit (同步) ←───┘
│修改
▼
State (響應(yīng)式對(duì)象)
│
▼
通知組件更新
四、vuex 常見的面試追問(wèn)點(diǎn):
面試官追問(wèn) | 推薦回答 |
state是如何實(shí)現(xiàn)響應(yīng)式的? | 基于Vue自身的響應(yīng)式系統(tǒng):使用Vue.observable或Vue實(shí)例實(shí)現(xiàn) |
為什么只能通過(guò)mutation修改state? | 保證所有的狀態(tài)修改有跡可循,便于追蹤變化、調(diào)試與維護(hù) |
為什么actions允許異步而mutations不允許異步? | 因?yàn)閙utation必須是可預(yù)測(cè)、可追蹤的同步修改狀態(tài),異步邏輯統(tǒng)一封裝在actions中,更好維護(hù) |
什么時(shí)候用 getters? | 當(dāng)store數(shù)據(jù)需要做復(fù)雜計(jì)算或多組件共享計(jì)算邏輯時(shí) |
五、總結(jié):Vuex 實(shí)現(xiàn)原理的核心思想
- Vuex 實(shí)質(zhì)是利用 Vue 的響應(yīng)式系統(tǒng)。
- 統(tǒng)一狀態(tài)數(shù)據(jù)到單例 store 中,提供明確、規(guī)范的狀態(tài)修改方式(Mutation 同步、Action 異步)。
- 通過(guò)嚴(yán)格模式、輔助方法確保開發(fā)規(guī)范,提供良好開發(fā)體驗(yàn)。