Vue source code Vuex (4) Logger plug-in

学习内容和文章内容来自 黄轶老师
"Vue.js2.0 Source Code Demystification" ,
"Vue.js 3.0 Core Source Code Analysis"
这里分析的源码是Runtime + Compiler 的 Vue.js
调试代码在:node_modules\vue\dist\vue.esm.js 里添加
vue版本:Vue.js 2.5.17-beta

你越是认真生活,你的生活就会越美好!

Vue source code learning complete directory

plug-in

In addition to the access capabilities provided by Vuex, it also provides a plug-in capability that allows us to storemonitor change process of to do something.

Vuex's storeAccept pluginsoption, we can pass in plugins when Storeinstantiating , which is an array, and then Storewhen executing the constructor, these plugins will be executed:

const {
    
    
  plugins = [],
  strict = false
} = options
// apply plugins
plugins.forEach(plugin => plugin(this))

In our actual projects, what we use the most is the built-in Loggerplugin , which can help us track statechanges and output some formatted logs.

Let's analyze the implementation of this plug-in.

Loggerplug-in

LoggerThe plugin is defined src/plugins/logger.jsin :

export default function createLogger ({
    
    
  collapsed = true,
  filter = (mutation, stateBefore, stateAfter) => true,
  transformer = state => state,
  mutationTransformer = mut => mut,
  logger = console
} = {
    
    }) {
    
    
  return store => {
    
    
    let prevState = deepCopy(store.state)

    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
    })
  }
}

function repeat (str, times) {
    
    
  return (new Array(times + 1)).join(str)
}

function pad (num, maxLength) {
    
    
  return repeat('0', maxLength - num.toString().length) + num
}

The parameter received by the plug-in function is storean instance , which executes store.subscribethe method. First, let's look at the definition subscribeof :

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)
    }
  }
}

subscribeThe logic of is very simple, that is, add a function this._subscribersto and return a unsubscribemethod.

And when we store.commitexecute the method, we will traverse this._subscribersand execute their corresponding callback functions:

commit (_type, _payload, _options) {
    
    
  const {
    
    
    type,
    payload,
    options
  } = unifyObjectStyle(_type, _payload, _options)

  const mutation = {
    
     type, payload }
  // ...
  this._subscribers.forEach(sub => sub(mutation, this.state))  
}

Going back to our Loggerfunction , it is equivalent to subscribing mutationto the commit. Its prevStatemeans the previous one stateand the one afternextState the commit . Both of them need to execute the method to copy a copy of the object, so that their modifications will not affect the original .mutationstatestatedeepCopystore.state

Next, construct some formatted messages, print out some time messages message, the previous state prevState, the corresponding mutationoperation formattedMutationand the next state nextState.

Final update to prepare prevState = nextStatefor the next commit mutationoutput log.

Summarize

So far, the plug-in analysis of Vuex is over. Vuex supports plug-ins by design, allowing us to track storeinternal . LoggerPlug-ins also provide good guidance during our development stage.

Of course, we can also Vueximplement plug-ins to help us achieve some specific requirements.

Vue source code learning directory

Vue source code learning complete directory


谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强

Guess you like

Origin blog.csdn.net/weixin_42752574/article/details/122696468