vue instance initialization sequence

Posted by gasxtreme on Fri, 01 Oct 2021 18:29:56 +0200

vue data initialization

The logic of vue's underlying response is controlled by the Object.defineProperty() function. To begin with, the point of knowledge of this method is:

1. Object.defineProperty()

1.1 Object Definition and Assignment

The commonly used definition and assignment method obj.prop =value or obj['prop']=value

let obj = {}
obj.name = 'jack'
//perhaps
obj['name'] = 'tom'

1.2 Object.defineProperty() Syntax Description

Object.defineProperty(obj, prop, desc)

Role: The purpose of this method is to define a new attribute on an object or to modify an existing attribute.

Parameters:

  • obj needs to define the current object of the property
  • Property name that prop currently needs to define
  • desc attribute descriptor

1.3 Properties and Internal Properties

There are three types of properties for javacript

  • Named Data Attribute: An attribute that has a defined value. This is also the most common attribute
var flight = {
    airline: "Oceanic",
    number: 815,
    departure: {
        IATA: "SYD",
        time: "2004-09-22 14:55",
        city: "Sydney"
    },
    arrival: {
        IATA: "LAX",
        time: "2004-09-23 10:42",
        city: "Los Angeles"
    }
};
  • Named accessor properties: properties read and assigned through getter s and setter s, just like the set, get methods of java classes
var people = {
    name: "lyx",
    get value() {
        return "uuuuu";
    },
    set value(value) {
        console.log("==========")
        this.name = value;
    }
};

console.log(people.name); //lyx
console.log(people.value);//uuuuu //call accessor property value(getter)
people.value = "12344"; //Call accessor property value (setter)
console.log(people.name); //12344
  • Internal Attributes: Attributes used internally by the JavaScript engine cannot be accessed directly from JavaScript code, but they can be read and set indirectly through some methods. For example, each object has an internal attribute [[Prototype]], which you cannot access directly, but its value can be read indirectly through the Object.getPrototypeOf() method.

1.4 Attribute Descriptor

Object.defineProperty() defines attributes for objects in two forms and cannot be mixed, data descriptors and access descriptors

1.4.1 Data Descriptor

Value: value of props

Writable: is it writable

 let Person = {}
 Object.defineProperty(Person, 'name', {
     value: 'jack',
     writable: false
 })
console.log(Person.name)
// => jsck
Person.name = 'tom'
// =>TypeError: Cannot assign to read only property 'name' of object '#<Object>'"
 let Person = {}
 Object.defineProperty(Person, 'name', {
     value: 'jack',
     writable: true
 })
console.log(Person.name)
// => jsck
Person.name = 'tom'
console.log(Person.name)
// => tom

Default value for some descriptors: this is not only the data description but also the access descriptor

Property NameDefault valueAttribute Description
valueundefinedValue of props
getundefinedMethod of assignment
setundefinedMethod of Value
writablefalseWritable or not
enumerablefalseWhether attributes will appear in traversal for in or Object.keys()
configurablefalseWhether properties are configured and deleted
1.4.2 Access Descriptor getter setter
  • get: Provides a getter method for a property, default undefined

  • set: Provides a setter method for a property, default undefined

let Person = {}
let temp = 'bobo'
Object.defineProperty(Person, 'name', {
    get() {
        return temp
    },
    set(val) {
        temp = val
    }
})
console.log(Person.name)
// => bobo
Person.name = 'tom'
console.log(Person.name)
// => tom
1.4.3 Access descriptors and data descriptors all have the following descriptors
  • configrable describes whether properties are configured and deleted
  • enumerable describes whether an attribute appears in a for-in or Object.keys() traversal

When writable is true and configurable is false, props can be redefined

let Person = {}
Object.defineProperty(Person, 'name', {
    value: 'rose',
    configurable: false,
    writable: true
})
Object.defineProperty(Person, 'name', {
    value: 'jack'
})
console.log(Person.name)
// = > jack

props cannot be redefined when writable is false configurable is false

let Person = {}
Object.defineProperty(Person, 'name', {
    value: 'rose',
    configurable: false,
    writable: false
})
Object.defineProperty(Person, 'name', {
    value: 'jack'
})
// => TypeError: Cannot redefine property: name"
console.log(Person.name)

When writable is false configurable is true, props can be redefined on the prototype chain

let Person = {}
Object.defineProperty(Person, 'name', {
    value: 'rose',
    configurable: true,
    writable: false
})
Object.defineProperty(Person, 'name', {
    value: 'jack'
})
console.log(Person.name)
//=> jack

One more thing: you cannot delete this property on an object when configurable is false

writableconfigurableHandout
truefalseProps can be redefined and cannot be deleted (configurable cannot delete attributes well defined, but props cannot be redefined and ignored)
falsefalseprops cannot be redefined or deleted
falsetrueprops can be redefined or deleted
let Person = {}
Object.defineProperty(Person, 'name', {
    value: 'rose',
    configurable: false,
    writable: true
})
delete Person.name
//=> "TypeError: Cannot delete property 'name' of #<Object>"
1.4.4 enumerable snippet analysis
let Person = {}
Object.defineProperty(Person, 'name', {
    value: 'rose',
    enumerable: false
})
Person.age = '23'
console.log(Person)
// =>{age: '23', name: 'rose'}
for (let item in Person) {
    console.log(item)
}
//=> age

Attribute cannot be traversed when its enumerable descriptor is false

Tips: Differences in how data is defined

Increase Knowledge
let Person = {}
Person.render = 'male'
//Equivalent to
Object.defineProperty(Person, 'render', {
    value: 'male',
    writable: true,
    configurable: true,
    enumerable: true
})
let Person = {}
Object.defineProperty(Person, 'render', {
    value = 'female'
})
//Equivalent to
Object.defineProperty(Person, 'render', {
    value: 'female',
    writable: false,
    configurable: false,
    enumerable: false
})
1.4.5 Invariance
1.4.5.1 Object Constant

Constant attributes are equivalent to unmodifiable, writable false, configurable false, and cannot be redefined or deleted

1.4.5.2 Prohibit extension of Object.preventExtensions()

Prevent objects from adding new attributes and retain existing attributes - Object.preventExtensions()

let Person = {}
Object.defineProperty(Person, 'name', {
    value: 'rose'
})
Object.preventExtensions(Person)
Person.age = '23'
// = >"TypeError: Cannot add property age, object is not extensible"
console.log(Person)
1.4.5.3 Seal Object.seal()

Object.seal() = Object.preventExtension() + configurable: false

In addition to modifying the value of an object's existing property, no new property can be added or deleted.

1.4.5.4 Freeze Object.freeze()

Object.freeze() = Object.seal() + writable: false

You cannot delete frozen objects, add new attributes, or modify the values of attributes.

This method is the highest level of immutability that you can apply to an object, which prohibits modifications to the object itself and any of its direct properties (but other objects referenced by this object are unaffected). You can freeze an object deeply by calling Object.freeze() on it first.Then iterate through all the objects it references and call Object.freeze() on them. Be careful, though, because doing so may inadvertently freeze other shared objects.

2.Vue Change Detection

Data detection for Vue is done by intercepting attributes that change data.

2.1 Object Change Detection

The primary key to vue's data-driven view is how we know that the data has changed.

For objects, JS provides the Object.defineProperty method, which can get values from the object, assign values from the set, and know that the data has changed from the set method.

let car = {}
let val = 3000
Object.defineProperty(car, 'price', {
  enumerable: true,
  configurable: true,
  get(){
    console.log('price Property was read')
    return val
  },
  set(newVal){
    console.log('price Property modified')
    val = newVal
  }
})

3.Vue life cycle

As we can see from the diagram, the life cycle of a Vue instance can be roughly divided into four phases:

  • Initialization phase: Initialize some properties, events, and responsive data for the Vue instance;
  • Template compilation phase: compile the template into a rendering function;
  • Mount phase: mount the instance onto the specified DOM, rendering the template into the real DOM;
  • Destroy phase: delete the instance itself from the parent component and remove dependencies on tracing and event listeners;

3.1 Initialization phase new Vue

The life cycle of a Vue instance is divided into the four phases above, where the initialization phase basically does two things

  • Create an instance of new Vue()
  • Initialize some events, attributes, responsive data, etc. for the created instance object;

3.1.1 new Vue()

Create an instance Vue

function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}

The constructor of the Vue class calls the init function:

this._init(options)

Call the _init(options) method on the prototype and pass in the option options written by the user. Where does this _init method come from? There are several lines of code below the Vue class definition, one of which is:

initMixin(Vue)

The source code for initMixin is as follows

export function initMixin (Vue) {
  Vue.prototype._init = function (options) {
    const vm = this
    vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
    )
    vm._self = vm
    initLifecycle(vm) //Initialize life cycle
    initEvents(vm)  // Initialization Event
    initRender(vm)  //Initialize Rendering
    callHook(vm, 'beforeCreate')
    initInjections(vm) // Initialize injections resolve injections before data/props
    initState(vm)   //Initialize props,methods,data,computed,watch
    initProvide(vm) //Initialize provide resolve provide after data/props
    callHook(vm, 'created')

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }
}

In addition to calling the initialization function to initialize related data, the callHook function was called at the appropriate time to trigger the hook of the life cycle-----> After all the initialization work has been completed, finally determine if the user passed in the el option If passed in, call the $mount function to enter the template compilation and mount phase, if not, do not enter the next life cycle phase, requiring the user to manually execute the vm.$mount method to enter the next life cycle phase.

4. Summary

Vue life cycle order:

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeDestroy
  • destroyed

The Vue life cycle is divided into four phases:

  • Initialization phase
  • Template Compilation Phase
  • Mount Phase
  • Destruction phase

The order in which classes are executed during the Vue initialization phase:

new Vue

  • _init(options)
    • initLifecycle
    • initEvents
    • initRender
    • callHook(vm, 'beforeCreate')
    • initInjections
    • initState
      • initProps
      • initMethods
      • initData
      • initComputed
      • initWatch
    • initProvide
    • callHook(vm, 'created')

Therefore, each property in a component is executed in the following sequence:

  • inject
  • props
  • method
  • data
  • computed
  • watch
  • provide

Topics: Javascript Vue Vue.js