Connected to Wen Jixu analysis, in the trigger beforeCreate lifecycle hook, perform:

initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created');
Copy the code

initInjections

Dependency injection, used to transfer values between hierarchical components, is not responsive.

Check whether $options.inject exists, and then recursively check whether there is an injection value in the vm._provided property value in the parent element of the resolveInject. The set method cannot be overridden, that is, cannot change the injected value.

initState

function initState(vm) {
  vm._watchers = [];
  var opts = vm.$options;

  if (opts.props) {
    initProps(vm, opts.props);
  }

  if (opts.methods) {
    initMethods(vm, opts.methods);
  }

  if (opts.data) {
    initData(vm);
  } else {
    observe(
      (vm._data = {}),
      true
      /* asRootData */
    );
  }

  if (opts.computed) {
    initComputed(vm, opts.computed);
  }

  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch);
  }
}
Copy the code

The fields provided by the user are initialized in sequence to check whether the field name is valid. The order is: props, Methods, data, computed, and watch.

props

If it is the props of a subcomponent, execute a loop on each propsOptions, where the propsOptions key is stored in the vm.$options._propKeys, and verify the props type. Then store each item in vM. _props and listen. The set method cannot be overridden, that is, cannot change the injected value.

methods

Initializing methods will append methods to Vue instance VM after validation.

data

If it is not a component, it initializes data with getData() => data() => mergedInstanceDataFn(), The mergedInstanceDataFn returned by Strats when processing data in the mergeOptions method. Where mergeData takes parent data and its own data and returns it.

If it is a component, execute data(), i.e. execute the data function in the passed options, and return the data object value and assign it to _data. Make sure data returns a new object for the function, otherwise if you declare the same component multiple times in the template, data in the component will point to the same reference.

Then the validity of each item in data is judged, and then the proxy(VM, “_data”, key) is executed to mount the key on the VM instance and listen to all the attributes of the first layer of data. Return VM [‘_data’][‘ someData ‘] or VM [‘_data’][‘ someData ‘] = val

After the loop completes, then execute:

observe(data, true /* asRootData */); / / the _data while forming
Copy the code

If __ob__ does not exist in data, execute:

var Observer = function Observer(value) {
  this.value = value;
  this.dep = new Dep();
  this.vmCount = 0;
  def(value, '__ob__'.this);

  if (Array.isArray(value)) {
    if (hasProto) {
      protoAugment(value, arrayMethods);
    } else {
      copyAugment(value, arrayMethods, arrayKeys);
    }

    this.observeArray(value); // Recursively iterate over each item in the listener array
  } else {
    this.walk(value); // Recursively iterate over each property of the listener}};Copy the code

This method recursively initializes the subscriber list for each property and its subproperties. When a property is read, the current watcher is added to the subscription list for that property. When a property is set, all watcher in the subscription list are notified to perform their corresponding update method.

__ob__

__ob__ is an Observer instance. Each monitored object (including arrays) has an __ob__ attribute that holds the data value and a list of subscriptions to that data. You can add a subscription to this in reactiveGetter:

if (childOb) {
  childOb.dep.depend();

  if (Array.isArray(value)) {
    dependArray(value); // Loop over each item in the array to add a subscription}}Copy the code

protoAugment

Where, the listener of the corresponding array type is executed protoAugment, and the __proto__ of value (array type) is rewritten to arrayMethods, so that the array method will be intercepted and the mutation method rewritten in arrayMethods object will be executed when the array method is executed. Trigger notification to subscribe to the list of array subscriptions in the mutation method.

An array of key

When Vue is updating a list of elements rendered using V-for, it defaults to the “update in place” policy. Without the key, when the array order changes, the value will be updated directly in place because it is similar to a vnode in the same location (sameVnode), and an error will occur if the item relies on child component state or temporary DOM state. Add a key to make vue’s update Dren loop more accurate.

However, if the key value is index, then each key in the old and new vNodes will be the same, which will have no effect. It will still update in place without finding the same node.

Considerations for detecting changes (from documentation)

  • For objects:VueUnable to detectpropertyAdd or remove. Due to theVueProperties are executed when the instance is initializedgetter/setterTransform, so the property must be indataObjects exist to makeVueConvert it to reactive;
  • For arrays:VueUnable to listen to set array items by index (i.e., subscript) (performance reasons) and change array length (lengthProperties cannot be setget/set).

computed

After judging whether each item in computed tomography was SSR, the following results were performed:

watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions);
Copy the code

Where watchers is vm._computedWatchers, here instantiates a calculated Watcher, where computedWatcherOptions is {lazy: True}, so you don’t get the value immediately and therefore don’t trigger get to increase the subscription. Then execute:

defineComputed(vm, key, userDef);
Copy the code

Methods will be key in mount under the instance, the get method for computedGetter (execution createComputedGetter (key) (curry) results), set method Settings cannot be rewritten.

watch

Execute each item in watch:

createWatcher(vm, key, handler);
Copy the code

$watch(expOrFn, expOrFn, cb, options) new Watcher(VM, expOrFn, cb, options) ExpOrFn :’info’,’cb’:’handler’,’options’:'{handler: handler,deep: true,user: true}’. Where user: true indicates the watcher written by the user.

This. Get ->this. Getter = getvalue = getvalue = getvalue = getvalue = getvalue The watcher is then subscribed to the corresponding variable (which Watcher pushes into the instance attribute subs of the Dep), and the watcher list in the subS is notified to update when the variable changes later.

In other words, when expression is executed to obtain the corresponding value, the watcher will be added to the monitored attribute involved in expression, that is, subscription. The Watcher will be notified to update when the variable changes later.

At this point, because deep: True, so traverse(value) on finally in watcher.prototype. get to recursively read each property of the value object (including the array), triggering the proxyGetter that listens for each variable, Subscribe the Watcher to all variables.

After checking whether the control is immediate, unwatchFn provides the execution method of destroying the watcher.

initProvide

Determine if $options.provide exists and assign it to the vm._provided property.

Trigger created hook

callHook(vm, 'created');
Copy the code

Execute the lifecycle hook Created and print vue Created.

The summary of this chapter

  1. This chapter introducesvueperformcreatedStage;
  2. Dependency injection was initializedinject/provideRelated;
  3. rightoptionsIn theProps, Methods, Data, computed, watchProperty to do things like listen, bind, subscribe, and so on, including array listening and so on.