1、使用Logger插件
import createLogger from 'vuex/dist/logger'
const store = new Vuex.Store({
plugins: [createLogger()]
})
2、基本實現
一、在Store的構造器中定義了 this._subscribers = [] ,提供subscribe 方法收集訂閱者,之後在commit mutation時, 遍歷其._subscribers執行訂閱者的回調方法。
subscribe (fn) {
return genericSubscribe(fn, this._subscribers)
}
function genericSubscribe (fn, subs) {
if (subs.indexOf(fn) < 0) {
subs.push(fn)
}
return () => {
const i = subs.indexOf(fn)
if (i > -1) {
subs.splice(i, 1)
}
}
}
commit(){
....
handler()
this._subscribers.forEach(sub => sub(mutation, this.state))// handler執行之後,訂閱者執行
....
}
二、createLogger()方法中,執行store.subscribe(( mutation, state )=>{}) 來訂閱mutation的變化
logger.js
createLogger() 的配置項
export default function createLogger ({
collapsed = true,//打印記錄是否自動展開
filter = (mutation, stateBefore, stateAfter) => true,//可以指定某些mutation不需要log 比如return mutation.type !== "thisMutationName" 傳入false
transformer = state => state, //在開始記錄之前轉換狀態 例如,只返回指定的子樹 return state.subTree
mutationTransformer = mut => mut,// mutation 按照 { type, payload } 格式記錄 我們可以按任意方式格式化 例如 只記錄名稱 return mutation.type
logger = console //自定義console的實現,默認爲‘console’
} = {}) {
return store = >{....}
}
訂閱mutation的變化,打印記錄
return store => {
let prevState = deepCopy(store.state)//對原state深度copy
/**
添加訂閱
**/
store.subscribe((mutation, state) => {
if (typeof logger === 'undefined') {
return
}
const nextState = deepCopy(state)
if (filter(mutation, prevState, nextState))
const time = new Date()
const formattedTime = ` @ ${pad(time.getHours(), 2)}:${pad(time.getMinutes(), 2)}:${pad(time.getSeconds(), 2)}.${pad(time.getMilliseconds(), 3)}`
const formattedMutation = mutationTransformer(mutation)
const message = `mutation ${mutation.type}${formattedTime}`
const startMessage = collapsed
? logger.groupCollapsed
: logger.group
// render
try {
startMessage.call(logger, message)
} catch (e) {
console.log(message)
}
logger.log('%c prev state', 'color: #9E9E9E; font-weight: bold', transformer(prevState))
logger.log('%c mutation', 'color: #03A9F4; font-weight: bold', formattedMutation)
logger.log('%c next state', 'color: #4CAF50; font-weight: bold', transformer(nextState))
try {
logger.groupEnd()
} catch (e) {
logger.log('—— log end ——')
}
}
prevState = nextState
})
}
3、總結
- Vuex從設計上是支持插件,讓我們很好地從外部追蹤store內部的變化。
- Logger插件就在開發階段提供了對mutation變化的監聽,來實現打印記錄。
- 我們也可以自定義Vuex插件實現一些特定的需求。