Vue2. X response analysis:
Core API: Object. DefineProperty
The responsive principle: Views update as data changes
Simple analysis:
- Loop through all the properties of the data Object and convert them to getters/setters using Object.defineProperty
- Object: Recursive traversal
- Array: Function interceptor that overrides array prototype methods
Disadvantages:
- Deep monitoring, need to recurse to the end, one-time calculation is large
- Unable to native listen array, requires special handling
- Vue. Set and Vue. Delete are used to handle the failure of listening on new attributes and deleting attributes
Code simple demo:
// Publish subscribe mode
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
// Notify the view to update
notify() {
this.subs.forEach(item= >{ item.update(); }); }}/ / observer
class Watch {
constructor() {
Dep.target = this;
}
update() {
console.log("Update view"); }}function render() {
console.log("Update view");
}
function defineReactive(obj, key, val) {
const dep = new Dep();
observal(val);
Object.defineProperty(obj, key, {
get: function() {
console.log("get", val);
dep.addSub(Dep.target);
return val;
},
set: function(newVal) {
if(newVal ! = val) {console.log("set", val);
// The new value also requires deep listeningobserval(val); val = newVal; dep.notify(); }}}); }// Rewrite the prototype
const nativeArrayProperty = Array.prototype;
// Create a new object without affecting the prototype
const arrayPro = Object.create(nativeArrayProperty);
const methodsToPatch = [
"push"."pop"."shift"."unshift"."splice"."sort"."reverse"
];
methodsToPatch.forEach(method= > {
arrayPro[method] = function() {
nativeArrayProperty[method].call(this. arguments);// Update the view
render();
};
});
// Listen for object properties
function observal(target) {
if (typeoftarget ! ="object" || target == null) {
return target;
}
if (Array.isArray(target)) {
target.__proto__ = arrayPro;
}
for (let key intarget) { defineReactive(target, key, target[key]); }}class TVue {
constructor(options) {
this.data = options.data;
observal(this.data);
newWatch(); }}let vue = new TVue({
data: {
leftNode: 1.rightNode: "20".info: {
// Deep monitor
name: "luck".age: 10
},
nums: [10.20.30]}});console.log(vue.data.leftNode);
vue.data.info.age = 20
vue.data.nums.push(40);
Copy the code
The principle of Vue3.0 responsiveness
Vue3 uses the ES6 Proxy feature to achieve responsiveness
Proxy
Proxy can be understood as a layer of “interception” before the target object. All external access to the object must pass this layer of interception. Therefore, Proxy provides a mechanism for filtering and rewriting external access. The word Proxy is used to mean that it acts as a Proxy for certain operations.
Proxy basic application:
const data = {
name: "luck".age: 21
};
// Array manipulation
// const data = [1,2,3,4]
/** * get(target, propKey, receiver) intercepts reading of object properties * set(target, propKey, value, receiver) : intercepts setting of object properties * has(target, propKey) : * deleteProperty(target, propKey) : Intercepts the operation of delete Proxy [propKey] and returns a Boolean. * ownKeys (target) : interception Object. GetOwnPropertyNames (proxy), Object. GetOwnPropertySymbols (proxy), the Object. The keys (proxy), for... The in loop returns an array. This method returns the attribute names of all the target object's own attributes *... * /
let proxy = new Proxy(data, {
/ * * * *@param {*} Target: indicates the target object *@param {*} Key: attribute name *@param {*} Receiver: Proxy instance itself (optional) *@returns* /
get(target, key, receiver) {
const result = Reflect.get(target, key, receiver);
// const result = target[key]
return result;
},
set(target, key, val, receiver) {
// Duplicate data is not processed
if (val === target[key]) {
return true;
}
const result = Reflect.set(target, key, val, receiver);
// const result = target[key] = value;
console.log("set", key, val);
return result;
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key);
console.log("delete property", key);
returnresult; }});// get
const age = proxy.age;
// set
proxy.name = "code";
// delete
const result = delete proxy.name;
// push
proxy.push(5)
Copy the code
Reflect
- The Reflect method corresponds to the Proxy method. As long as it is a Proxy method, the corresponding method can be found on the Reflect object
- Make Object operations more normalized, standardized, and functional
- Put some utility functions of Object (such as Object.defineProperty) on Reflect.
/ / the old way
'name' in data // true
delete data.name
/ / a new way
Reflect.has(data, 'name') // true
Reflect.deleteProperty(data,'name')
Copy the code
The proxy summary:
Advantages: Can avoid Object. DefineProperty problem
- Deep listening: better performance – it does not recurse to the end but only when it gets to the level
- Listen for array changes
- You can listen to add and delete properties
Cons: Not compatible with all browsers, and not polyfill
Reactive simple processing:
function reactive(target = {}) {
if (typeoftarget ! = ="object" || target == null) {
return target;
}
// Proxy configuration
const proxyConf = {
get(target, key, receiver) {
const result = Reflect.get(target, key, receiver);
// Deep monitor
// Performance improvement: When does get reach this level do recursion
return reactive(result);
},
set(target, key, val, receiver) {
// Duplicate data is not processed
if (val === target[key]) {
return true;
}
const ownKeys = Reflect.ownKeys(target);
if (ownKeys.includes(key)) {
console.log("Existing key", key);
} else {
console.log("新增的 key", key);
}
const result = Reflect.set(target, key, val, receiver);
console.log("set", key, val);
return result;
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key);
console.log("delete property", key);
return result; // Check whether the deletion is successful}};// Generate a proxy object
const observed = new Proxy(target, proxyConf);
return observed;
}
let data = {
name: "luck".age: 33.address: {
city: "sz"
},
arr: [1.2.3.4]};const proxyData = reactive(data);
Copy the code