Table of contents
Introduction to Vue
Vue.js is an open-source progressive JavaScript front-end framework mainly used for building user interfaces and single-page applications (SPA). Vue.js can be easily integrated with other libraries or existing projects and is considered an effective way to develop responsive data-driven modern web applications.
Core features of Vue.js:
- Responsive data binding: Vue.js can respond to user input and page changes through two-way binding of data.
- Componentization: Vue.js allows developers to turn a single component into an independent module, which has excellent performance and can be reused.
- Template-based syntax: Vue.js provides a template syntax that allows developers to simply write HTML templates and bind them to Vue.js components.
The responsive principle of Vue2
Vue2's responsive principle is based Object.defineProperty()
on , which can define the properties of objects and hijack them. When the property value changes, Vue can detect the change and re-render the corresponding page content.
The specific implementation principle is as follows:
- In the initialization phase of Vue, Vue will recursively hijack the incoming
data
object anddata
convert all properties of the object intogetter/setter
the form . - When data is used in the page, Vue will trigger
getter
the function , thusWatcher
adding the current (observer) object to the dependency of the current property. - When the data changes, Vue will detect the change through the listener and trigger
setter
the function , thereby notifying all dependencies under the propertyWatcher
to update; Watcher
After the object is notified, it will send a message to the corresponding component to notify that the view needs to be re-rendered, so as to update the entire page.
It should be noted that Vue2 can only monitor the changes of object properties, and cannot monitor the changes of adding/deleting object properties and array methods, so we can use Vue.set()
the or Vue.delete()
update object properties, but we can only use native JavaScript arrays push()
, pop()
, splice()
, shift()
, unshift()
methods etc. to manipulate arrays.
The sample code of Vue2 data hijacking is as follows:
const data = {
msg: 'Hello Vue' }
Object.defineProperty(data, 'msg', {
get() {
console.log('get');
return val;
},
set(newValue) {
console.log('set', newValue);
val = newValue;
}
})
Detailed Explanation of Object.defineProperty()
Object.defineProperty() is a new method in ES5, which is used to define new properties for objects or modify properties of objects. Its syntax is as follows:
Object.defineProperty(obj, prop, descriptor)
The meaning of the parameters:
- obj: The object whose properties are to be defined.
- prop: The name of the property to define or modify.
- descriptor: The attribute descriptor object that needs to be defined or modified.
The property descriptor object contains the following optional properties:
- value: The value of the attribute, which is undefined by default.
- writable: If true, the value of the property can be changed by assignment operator, default is false.
- enumerable: If true, the property can be enumerated when enumerating object properties, the default is false.
- configurable: if true, you can use the Object.defineProperty() method to modify the property's descriptor, the default is false.
- get: attribute reading method.
- set: attribute assignment method.
Disadvantages of Object.defineProperty()
- Unable to monitor the changes of the array.
Vue2
Define the method that will modify the original array as a mutation method.
Mutation methods such aspush、pop、shift、unshift、splice、sort、reverse
etc. cannot triggerset
.
Non-mutating methods, such asfilter,concat,slice
etc. , will not modify the original array, but will return a new array.
Vue2
The best approach is to rewrite these mutation methods to monitor array changes. - Each property of the object must be traversed. In most
cases, it is necessary to cooperate with and traverse, so there is an additional layer of nesting. And because of traversal, if a certain property on the object does not need to be "hijacked", but "hijacking" will still be added to it at this time.Object.defineProperty
Object.keys
- Nested objects must be traversed deeply
When an object is deeply nested, it must be traversed layer by layerObject.defineProperty()
until .
The responsive principle of Vue3
Vue3's responsive principle mainly uses ES6's Proxy
instead of Vue2 Object.defineProperty()
's, so as to achieve more efficient and powerful data hijacking and responsiveness.
Proxy objects can implement data hijacking by intercepting access and modification data. The Reflect object provides more flexible and easy-to-use data manipulation methods. For example, you can use Reflect.has() to check whether an object has a certain property, and use Reflect.defineProperty() instead of Object.defineProperty().
The specific implementation principle is as follows:
-
In the initialization phase of Vue3, Vue3 will proxy the incoming
data
object by usingProxy
the object, that is, usenew Proxy(target, handler)
, wheretarget
is the object to be proxied,handler
and is an object used to define the operationtarget
in . -
When the data is used in the page, Vue3 will trigger
get
the operation , the proxy objecthandler.get()
will be called, and then lethandler
capture the operation, andWatcher
add the current (observer) object to the dependency of the current property. -
When the data changes, Vue3 will detect the change through the listener, and trigger
set
the operation , and the proxy objecthandler.set()
will be called, thereby notifying all dependent 'Watcher' objects under the property to update; -
Watcher
After the object is notified, it will send a message to the corresponding component to notify that the view needs to be re-rendered, so as to update the entire page.
The code for implementing data responsiveness using Proxy objects in Vue3 is as follows:
const data = {
msg: 'Hello Vue' }
const reactiveData = new Proxy(data, {
get(target, key) {
console.log('get');
return target[key];
},
set(target, key, value) {
console.log('set');
target[key] = value;
return true;
}
})
In the above code, data
the object reactiveData
is reactiveData
. When accessing the properties of the object, the get() function inside the Proxy object is called; when setting the property, the set() function inside the Proxy object is called. In the get() and set() functions, the reading and assignment of attributes can be intercepted, so as to realize the responsiveness of data.
Detailed Proxy
Proxy is a new object added in ES6. It is used to proxy another object and intercept a series of operations such as reading, assigning, and defining properties of the object. Its syntax is as follows:
new Proxy(target, handler)
Parameters in Proxy:
- target: The target object to be proxied.
- handler: An object whose property is a hook function (trap), used to intercept the operation of the proxy object.
handler contains the following optional hook functions (trap):
- get(target, prop): used to intercept the read operation of the object.
- set(target, prop, value): used to intercept the assignment operation of the object.
- has(target, prop): used to intercept the in operation.
- deleteProperty(target, prop): used to intercept delete operations.
- apply(target, thisArg, args): used to intercept function calls.
- construct(target, args): used to intercept the new operation.
Advantages of Proxy
Proxy
Objects can be monitored directly instead of properties;Proxy
You can directly monitor the changes of the array;Proxy
What is returned is a new object, we can only operate the new object to achieve the purpose, butObject.defineProperty
can only traverse the object properties and directly modify;