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 Name | Default value | Attribute Description |
---|---|---|
value | undefined | Value of props |
get | undefined | Method of assignment |
set | undefined | Method of Value |
writable | false | Writable or not |
enumerable | false | Whether attributes will appear in traversal for in or Object.keys() |
configurable | false | Whether 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
writable | configurable | Handout |
---|---|---|
true | false | Props can be redefined and cannot be deleted (configurable cannot delete attributes well defined, but props cannot be redefined and ignored) |
false | false | props cannot be redefined or deleted |
false | true | props 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