Vuex中內置Logger插件的源碼分析

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插件實現一些特定的需求。
發佈了32 篇原創文章 · 獲贊 26 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章