SoFunction
Updated on 2025-04-05

Detailed explanation of the execution order of created, watch and computed in vue

Preface

Interview questions:vuemiddlecreatedwatch(immediate: true)andcomputedWhat is the execution order?

Let’s take a look at a simple example:

// 
import Vue from "vue";

new Vue({
  el: "#app",
  template: `<div>
    <div>{{computedCount}}</div>
  </div>`,
  data() {
    return {
      count: 1,
    }
  },
  watch: {
    count: {
      handler() {
        ('watch');
      },
      immediate: true,
    }
  },
  computed: {
    computedCount() {
      ('computed');
      return  + 1;
    }
  },
  created() {
    ('created');
  },
});

The execution order of the current example is:watch --> created --> computed

Why?

existnew VueDuring the instantiation process, the initialization method will be executedthis._init, which has the code:

._init = function (options) {
    // ...
    initState(vm);
    // ...
    callHook(vm, 'created');
    // ...
    if (vm.$) {
      vm.$mount(vm.$);
    }
}

function initState (vm) {
  vm._watchers = [];
  var opts = vm.$options;
  if () { initProps(vm, ); }
  if () { initMethods(vm, ); }
  if () {
    initData(vm);
  } else {
    observe(vm._data = {}, true /* asRootData */);
  }
  if () { initComputed(vm, ); }
  if ( &&  !== nativeWatch) {
    initWatch(vm, );
  }
}

I looked at the code and found out that I had executed it firstinitComputed(vm, ), and then executeinitWatch(vm, ), execute againcallHook(vm, 'created'), then why notcomputed --> watch --> createdWoolen cloth?

Don't worry, listen to my story.

1. About initComputed

const computedWatcherOptions = { lazy: true }
function initComputed (vm: Component, computed: Object) {
  // $flow-disable-line
  const watchers = vm._computedWatchers = (null)
  // computed properties are just getters during SSR
  const isSSR = isServerRendering()

  for (const key in computed) {
    const userDef = computed[key]
    const getter = typeof userDef === 'function' ? userDef : 
    // ...
    if (!isSSR) {
      // create internal watcher for the computed property.
      watchers[key] = new Watcher(
        vm,
        getter || noop,
        noop,
        computedWatcherOptions
      )
    }

    // component-defined computed properties are already defined on the
    // component prototype. We only need to define computed properties defined
    // at instantiation here.
    if (!(key in vm)) {
      defineComputed(vm, key, userDef)
    } else if (.NODE_ENV !== 'production') {
        // ...
    }
  }
}

ByinitComputedWhen initializing the computed attribute, the current component is processed through traversal.computed. First, when instantiating the computed attribute,{ lazy: true }Passed in as parameters and instantiatedWatcherIn-housegetterIt's in the current examplecomputedCountfunction; secondly, bydefineComputed(vm, key, userDef)The way to the current component instancevmThe above iskeyconductuserDefhandling. Specifically:

export function defineComputed (
  target: any,
  key: string,
  userDef: Object | Function
) {
  const shouldCache = !isServerRendering()
  if (typeof userDef === 'function') {
     = shouldCache
      ? createComputedGetter(key)
      : createGetterInvoker(userDef)
     = noop
  }
  // ...
  (target, key, sharedPropertyDefinition)
}

function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      if () {
        ()
      }
      if () {
        ()
      }
      return 
    }
  }
}

From the above, it can be seen that here(target, key, sharedPropertyDefinition)The way to change the functioncomputedGetterAsgetFunction, only whenkeyThe internal logic will be triggered when access is made. Internal logic()for:

evaluate () {
     = ()
     = false
}

getThere are main logic in it:

value = (vm, vm)

HereThat's in the current example:

computedCount() {
  ('computed');
  return  + 1;
}

That is, only when obtainingcomputedCountIt will trigger whencomputedThe calculation is to performvm.$mount(vm.$)The stage will be executed('computed')

2. About initWatch

function initWatch (vm: Component, watch: Object) {
  for (const key in watch) {
    const handler = watch[key]
    if ((handler)) {
      for (let i = 0; i < ; i++) {
        createWatcher(vm, key, handler[i])
      }
    } else {
      createWatcher(vm, key, handler)
    }
  }
}
function createWatcher (
  vm: Component,
  expOrFn: string | Function,
  handler: any,
  options?: Object
) {
  if (isPlainObject(handler)) {
    options = handler
    handler = 
  }
  if (typeof handler === 'string') {
    handler = vm[handler]
  }
  return vm.$watch(expOrFn, handler, options)
}

ByinitWatchWhen initializing the listener, ifwatchis an array, then traversal executioncreateWatcher, otherwise it will be executed directlycreateWatcher. ifhandlerWhen it is an object or a string, it is processed and finally passed into it as a parameter.vm.$watchIn the middle, specifically:

.$watch = function (
    expOrFn: string | Function,
    cb: any,
    options?: Object
  ): Function {
    const vm: Component = this
    if (isPlainObject(cb)) {
      return createWatcher(vm, expOrFn, cb, options)
    }
    options = options || {}
     = true
    const watcher = new Watcher(vm, expOrFn, cb, options)
    if () {
      try {
        (vm, )
      } catch (error) {
        handleError(error, vm, `callback for immediate watcher "${}"`)
      }
    }
    return function unwatchFn () {
      ()
    }
  }

Get it hereoptionsThere will beimmediate: truekey value, and pass = trueset upuserfortrue, then pass it as a parameter to performWatcherInstantiation of .

In the current examplefortrue, so it will be executed(vm, ), that is,vmAs the main body, execute immediatelycb. In the current examplecbthat ishandler

handler() {
    ('watch');
},

Here is the explanation of the current example('watch')It is the first to execute.

Then, the execution is completedinitComputedandinitWatchAfterwards, it will passcallHook(vm, 'created')Execute to life cycle('created')Now.

Last passedvm.$mount(vm.$)When rendering the page, you will create it firstvNode, you need to obtaincomputedCountthe value ofgetThe subsequent logic of the function is finally executed('computed')

P.S. Why does the watch in vue execute after mounted

First, when calling mounted, it will enter the defineReactive function, then call the set method in the function, pass the new value assigned in mounted, and send the message to the subscriber by calling ( ), and then update the subscriber's list.

Only then will the watch be rendered and the class that enters the Watcher

Summarize

aboutvuemiddlecreatedandwatchThe execution order is relatively simple, andcomputedIt is throughFor the currentvmDefine it and then create it latervNodeThe execution of the stage is triggeredgetFunction, finally executed to calculate attributescomputedCorresponding logic.

This is the article about the detailed explanation of the execution order of created, watch and computed in vue. This is the end. For more related contents of vue created, watch and computed execution order, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!