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插件实现一些特定的需求。

你可能感兴趣的:(Vuex)