preface
Hello, everyone, I am Lin Sanxin, we also know that the rookie usually write basic articles more, I always believe in two words
- Explain the most difficult points in the most plain language
- Foundation is a prerequisite for advancement
Vue3 has been around for a long time, and most companies are probably using it, but how is it better than Vue2? A lot of people don’t know. Today I will first tell you about Vue3’s response principle, by the way, Vue3’s response is better than Vue2’s response.
What’s good about it?
Ok, so let’s talk about why Vue3 is better than Vue2. May usually ask you: do you know how the Vue response is achieved? You can give a rough answer
- The response formula of Vue2 is based on
Object.defineProperty
Implementation of the - Vue3’s responsiveness is based on ES6
Proxy
To implement the
Yes, although the above answer is a little abstract, it does answer the core principle of the two versions of Vue responsiveness, and the good and bad of the two versions of Vue responsiveness is indeed reflected in the difference between Object.defineProperty and Proxy.
Vue2
We all know that Vue2’s response is based on Object.defineProperty, so I’ll take Object.defineProperty as an example
// response function
function reactive(obj, key, value) {
Object.defineProperty(data, key, {
get() {
console.log(Visited `${key}Attribute `)
return value
},
set(val) {
console.log(` will${key}By the - >${value}-> Set to ->${val}`)
if(value ! == val) { value = val } } }) }const data = {
name: 'Lin Three Hearts'.age: 22
}
Object.keys(data).forEach(key= > reactive(data, key, data[key]))
console.log(data.name)
// Access the name attribute
/ / Lin three hearts
data.name = 'sunshine_lin' // Change name from -> Lin -> to ->sunshine_lin
console.log(data.name)
// Access the name attribute
// sunshine_lin
Copy the code
From the above example, I think we all have an idea about Object.defineProperty. What’s the problem? What are the disadvantages of it? Caused yudha to abandon it in Vue3. Let’s see:
// Continue with the above code
data.hobby = 'Play basketball'
console.log(data.hobby) / / to play basketball
data.hobby = 'Play games'
console.log(data.hobby) / / playing video games
Copy the code
DefineProperty Object defineProperty Object defineProperty Data has a new hobby property, which can be accessed and set, but neither get nor set is triggered. Therefore, object.defineProperty only listens for attributes in the original Object, but does not listen for new attributes. This is why Vue2 uses vue. $set to modify new attributes of objects.
Vue3
Object.defineproperty () : Object defineProperty () : Object defineProperty () : Object defineProperty () : Object defineProperty
const data = {
name: 'Lin Three Hearts'.age: 22
}
function reactive(target) {
const handler = {
get(target, key, receiver) {
console.log(Visited `${key}Attribute `)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.log(` will${key}By the - >${target[key]}-> Set to ->${value}`)
Reflect.set(target, key, value, receiver)
}
}
return new Proxy(target, handler)
}
const proxyData = reactive(data)
console.log(proxyData.name)
// Access the name attribute
/ / Lin three hearts
proxyData.name = 'sunshine_lin'
// Change name from -> Lin -> to ->sunshine_lin
console.log(proxyData.name)
// Access the name attribute
// sunshine_lin
Copy the code
DefineProperty is the same as object.defineProperty, so why do you choose Proxy instead of object.defineProperty? Note, the most critical to come, that is the object new attribute, let’s see the effect:
proxyData.hobby = 'Play basketball'
console.log(proxyData.hobby)
// The Hobby property is accessed
/ / to play basketball
proxyData.hobby = 'Play games'
// Change hobby from -> playing basketball -> to -> playing games
console.log(proxyData.hobby)
// The Hobby property is accessed
/ / playing video games
Copy the code
So now you see how Vue3’s response is better than Vue2’s?
Vue3 response principle
With the benefits of Proxy out of the way, let’s talk formally about the core of Vue3’s responsive principle.
preface
Take a look at the following code
let name = 'Lin Three Hearts', age = 22, money = 20
let myself = `${name}This year,${age}Age, deposit${money}Yuan `
console.log(myself) // Lin Sanxin is 22 years old and has 20 yuan in her savings
money = 300
// Expectation: Lin Sanxin is 22 years old and has 300 yuan in savings
console.log(myself) // Reality: Lin Sanxin is 22 years old and has 20 yuan in savings
Copy the code
Think about it. I want myself to change with money. What should I do? ${money} ${money} ${name} ${age} ${name} ${age
let name = 'Lin Three Hearts', age = 22, money = 20
let myself = `${name}This year,${age}Age, deposit${money}Yuan `
console.log(myself) // Lin Sanxin is 22 years old and has 20 yuan in her savings
money = 300
myself = `${name}This year,${age}Age, deposit${money}Yuan ` // Execute again
// Expectation: Lin Sanxin is 22 years old and has 300 yuan in savings
console.log(myself) // Reality: Lin Sanxin is 22 years old and has 300 yuan in savings
Copy the code
effect
Each time money changes, I have to implement myself = ‘${name} this year ${age}, deposit ${money} ‘again to update myself
let name = 'Lin Three Hearts', age = 22, money = 20
let myself = ' '
const effect = () = > myself = `${name}This year,${age}Age, deposit${money}Yuan `
effect() // Execute once
console.log(myself) // Lin Sanxin is 22 years old and has 20 yuan in her savings
money = 300
effect() // Execute again
console.log(myself) // Lin Sanxin is 22 years old and has 300 yuan in her savings
Copy the code
In fact, this is also bad, do not believe you can look at the following situation
let name = 'Lin Three Hearts', age = 22, money = 20
let myself = ' ', ohtherMyself = ' '
const effect1 = () = > myself = `${name}This year,${age}Age, deposit${money}Yuan `
const effect2 = () = > ohtherMyself = `${age}At the age of${name}Had the${money}Yuan `
effect1() // Execute once
effect2() // Execute once
console.log(myself) // Lin Sanxin is 22 years old and has 20 yuan in her savings
console.log(ohtherMyself) // Lin Sanxin, 22, had 20 yuan
money = 300
effect1() // Execute again
effect2() // Execute again
console.log(myself) // Lin Sanxin is 22 years old and has 300 yuan in her savings
console.log(ohtherMyself) // Lin Sanxin, 22, had 300 yuan
Copy the code
To add ohtherMyself, you have to write another effect and execute it every time you update it. If you add a lot of ohtherMyself, you have to write a lot of effect function execution code every time.
Track and the trigger
The track function collects all the effect functions that depend on the money variable and places them in the DEP. Because Set can automatically de-weight. Once collected, the trigger function will be executed to notify all effect functions in DEP that depend on the money variable to execute whenever the money variable changes in the future, so as to realize the update of the dependent variable. So let’s take a look at the code, and then I’m going to show you a picture just in case you get dizzy.
let name = 'Lin Three Hearts', age = 22, money = 20
let myself = ' ', ohtherMyself = ' '
const effect1 = () = > myself = `${name}This year,${age}Age, deposit${money}Yuan `
const effect2 = () = > ohtherMyself = `${age}At the age of${name}Had the${money}Yuan `
const dep = new Set(a)function track () {
dep.add(effect1)
dep.add(effect2)
}
function trigger() {
dep.forEach(effect= > effect())
}
track() // Collect dependencies
effect1() // Execute once
effect2() // Execute once
console.log(myself) // Lin Sanxin is 22 years old and has 20 yuan in her savings
console.log(ohtherMyself) // Lin Sanxin, 22, had 20 yuan
money = 300
trigger() // Notify the variables myself and otherMyself to be updated
console.log(myself) // Lin Sanxin is 22 years old and has 300 yuan in her savings
console.log(ohtherMyself) // Lin Sanxin, 22, had 300 yuan
Copy the code
Objects?
So let’s talk about objects, and I’ll give you an example of how to implement their responses in a primitive way
const person = { name: 'Lin Three Hearts'.age: 22 }
let nameStr1 = ' '
let nameStr2 = ' '
let ageStr1 = ' '
let ageStr2 = ' '
const effectNameStr1 = () = > { nameStr1 = `${person.name}He's a rookie }
const effectNameStr2 = () = > { nameStr2 = `${person.name}A little genius }
const effectAgeStr1 = () = > { ageStr1 = `${person.age}Age is very old }
const effectAgeStr2 = () = > { ageStr2 = `${person.age}Age is still very young ah }
effectNameStr1()
effectNameStr2()
effectAgeStr1()
effectAgeStr2()
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Lin Sanxin is a rookie. Lin Sanxin is a genius. Twenty-two is very old
person.name = 'sunshine_lin'
person.age = 18
effectNameStr1()
effectNameStr2()
effectAgeStr1()
effectAgeStr2()
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Sunshine_lin is a rookie sunshine_lin is a genius 18 is old 18 is still young
Copy the code
The above code, we also see, feel write very brainless. Remember the DEP collection effect? Let’s think of the name and age in the Person object as two variables, each with its own dependent variable
- Name: nameStr1 and nameStr2
- Age: ageStr1 and ageStr2
Therefore, name and age should have their own DEPs and collect the corresponding effects of their dependent variables
A deP is a Set. A person has an age and a name, so it has two DEPs. We can use another ES6 data structure, Map, to store it
const person = { name: 'Lin Three Hearts'.age: 22 }
let nameStr1 = ' '
let nameStr2 = ' '
let ageStr1 = ' '
let ageStr2 = ' '
const effectNameStr1 = () = > { nameStr1 = `${person.name}He's a rookie }
const effectNameStr2 = () = > { nameStr2 = `${person.name}A little genius }
const effectAgeStr1 = () = > { ageStr1 = `${person.age}Age is very old }
const effectAgeStr2 = () = > { ageStr2 = `${person.age}Age is still very young ah }
const depsMap = new Map(a)function track(key) {
let dep = depsMap.get(key)
if(! dep) { depsMap.set(key, dep =new Set()}// For now, I'm going to write it dead
if (key === 'name') {
dep.add(effectNameStr1)
dep.add(effectNameStr2)
} else {
dep.add(effectAgeStr1)
dep.add(effectAgeStr2)
}
}
function trigger (key) {
const dep = depsMap.get(key)
if (dep) {
dep.forEach(effect= > effect())
}
}
track('name') // Collect the person.name dependency
track('age') // Collect person.age dependencies
effectNameStr1()
effectNameStr2()
effectAgeStr1()
effectAgeStr2()
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Lin Sanxin is a rookie. Lin Sanxin is a genius. Twenty-two is very old
person.name = 'sunshine_lin'
person.age = 18
trigger('name') // Notify the dependent variable of Person.name to be updated
trigger('age') // Notify the dependent variable of Person.age to be updated
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Sunshine_lin is a rookie sunshine_lin is a genius 18 is old 18 is still young
Copy the code
We only have one Person object. What if we have multiple objects? How to do? We all know that each object creates a Map to store the DEP of the attributes in the object (using a Set). If there are multiple objects, how do we store the Map of each object? Please see below
In fact, ES6 also has a new data structure called WeakMap, let’s use it to store the Map of these objects. So we need to modify the track and trigger functions to see what they look like before
const depsMap = new Map(a)function track(key) {
let dep = depsMap.get(key)
if(! dep) { depsMap.set(key, dep =new Set()}// For now, I'm going to write it dead
if (key === 'name') {
dep.add(effectNameStr1)
dep.add(effectNameStr2)
} else {
dep.add(effectAgeStr1)
dep.add(effectAgeStr2)
}
}
function trigger (key) {
const dep = depsMap.get(key)
if (dep) {
dep.forEach(effect= > effect())
}
}
Copy the code
The previous code only did the processing scheme of a single object, but now if you want multiple objects, you have to use WeakMap for transformation (the following code may be a little wordy, but it will take care of students with weak foundation)
const person = { name: 'Lin Three Hearts'.age: 22 }
const animal = { type: 'dog'.height: 50 }
const targetMap = new WeakMap(a)function track(target, key) {
let depsMap = targetMap.get(target)
if(! depsMap) { targetMap.set(target, depsMap =new Map()}let dep = depsMap.get(key)
if(! dep) { depsMap.set(key, dep =new Set()}// For now, I'm going to write it dead
if (target === person) {
if (key === 'name') {
dep.add(effectNameStr1)
dep.add(effectNameStr2)
} else {
dep.add(effectAgeStr1)
dep.add(effectAgeStr2)
}
} else if (target === animal) {
if (key === 'type') {
dep.add(effectTypeStr1)
dep.add(effectTypeStr2)
} else {
dep.add(effectHeightStr1)
dep.add(effectHeightStr2)
}
}
}
function trigger(target, key) {
let depsMap = targetMap.get(target)
if (depsMap) {
const dep = depsMap.get(key)
if (dep) {
dep.forEach(effect= > effect())
}
}
}
Copy the code
After the above transformation, we finally realize the dependency collection of multiple objects, let’s give it a try
const person = { name: 'Lin Three Hearts'.age: 22 }
const animal = { type: 'dog'.height: 50 }
let nameStr1 = ' '
let nameStr2 = ' '
let ageStr1 = ' '
let ageStr2 = ' '
let typeStr1 = ' '
let typeStr2 = ' '
let heightStr1 = ' '
let heightStr2 = ' '
const effectNameStr1 = () = > { nameStr1 = `${person.name}He's a rookie }
const effectNameStr2 = () = > { nameStr2 = `${person.name}A little genius }
const effectAgeStr1 = () = > { ageStr1 = `${person.age}Age is very old }
const effectAgeStr2 = () = > { ageStr2 = `${person.age}Age is still very young ah }
const effectTypeStr1 = () = > { typeStr1 = `${animal.type}He's a rookie }
const effectTypeStr2 = () = > { typeStr2 = `${animal.type}A little genius }
const effectHeightStr1 = () = > { heightStr1 = `${animal.height}That's pretty high }
const effectHeightStr2 = () = > { heightStr2 = `${animal.height}Still calculate very short ah }
track(person, 'name') // Collect the person.name dependency
track(person, 'age') // Collect person.age dependencies
track(animal, 'type') // animal.type dependency
track(animal, 'height') // Collect animal.height dependency
effectNameStr1()
effectNameStr2()
effectAgeStr1()
effectAgeStr2()
effectTypeStr1()
effectTypeStr2()
effectHeightStr1()
effectHeightStr2()
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Lin Sanxin is a rookie. Lin Sanxin is a genius. Twenty-two is very old
console.log(typeStr1, typeStr2, heightStr1, heightStr2)
Dog is a genius. 50 is tall. 50 is short
person.name = 'sunshine_lin'
person.age = 18
animal.type = 'the cat'
animal.height = 20
trigger(person, 'name')
trigger(person, 'age')
trigger(animal, 'type')
trigger(animal, 'height')
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Sunshine_lin is a rookie sunshine_lin is a genius 18 is old 18 is still young
console.log(typeStr1, typeStr2, heightStr1, heightStr2)
// The cat is a rookie. The cat is a genius. 20 is tall
Copy the code
Proxy
Through the above study, we have been able to achieve when data update, the dependent variable of followed him change, but there are still shortcomings, we can find that every time we always have to manually perform track function depend on the collection, and when the data changes, we have to manually perform the trigger function to update notification
So, is there a way to automatically collect dependencies and automatically notify updates? The answer is yes, Proxy can solve this problem for us. Reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive reactive
function reactive(target) {
const handler = {
get(target, key, receiver) {
track(receiver, key) // Collect dependencies while accessing
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
trigger(receiver, key) // Automatically notifies updates when setting the value}}return new Proxy(target, handler)
}
Copy the code
Then change the previous code, remove the manual track and manual trigger, and find that the previous effect can also be achieved
const person = reactive({ name: 'Lin Three Hearts'.age: 22 }) / / to reactive
const animal = reactive({ type: 'dog'.height: 50 }) / / to reactive
effectNameStr1()
effectNameStr2()
effectAgeStr1()
effectAgeStr2()
effectTypeStr1()
effectTypeStr2()
effectHeightStr1()
effectHeightStr2()
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Lin Sanxin is a rookie. Lin Sanxin is a genius. Twenty-two is very old
console.log(typeStr1, typeStr2, heightStr1, heightStr2)
Dog is a genius. 50 is tall. 50 is short
person.name = 'sunshine_lin'
person.age = 18
animal.type = 'the cat'
animal.height = 20
console.log(nameStr1, nameStr2, ageStr1, ageStr2)
// Sunshine_lin is a rookie sunshine_lin is a genius 18 is old 18 is still young
console.log(typeStr1, typeStr2, heightStr1, heightStr2)
// The cat is a rookie. The cat is a genius. 20 is tall
Copy the code
Maybe some students will be a little confused, a little confused about the above code, and maybe a little round, I thought I would explain the process to you through a diagram, the diagram may be compressed, I suggest to open a look
Solve write dead problem
There’s one place up there where we’re dead, if you remember, in the track function
function track(target, key) {
let depsMap = targetMap.get(target)
if(! depsMap) { targetMap.set(target, depsMap =new Map()}let dep = depsMap.get(key)
if(! dep) { depsMap.set(key, dep =new Set()}// For now, I'm going to write it dead
if (target === person) {
if (key === 'name') {
dep.add(effectNameStr1)
dep.add(effectNameStr2)
} else {
dep.add(effectAgeStr1)
dep.add(effectAgeStr2)
}
} else if (target === animal) {
if (key === 'type') {
dep.add(effectTypeStr1)
dep.add(effectTypeStr2)
} else {
dep.add(effectHeightStr1)
dep.add(effectHeightStr2)
}
}
}
Copy the code
In the real world, there will be more than two objects, and if you add an else if for every additional object, you can’t do that. So how do we solve this problem? The authors of Vue3 have come up with a clever way to solve this problem, using a global variable activeEffect. In fact, it is very simple, each effect function executes, put itself into the corresponding DEP, this can not need to write dead.
How can we implement this feature? We need to modify the effect function and the track function
let activeEffect = null
function effect(fn) {
activeEffect = fn
activeEffect()
activeEffect = null // Change to null immediately after execution
}
function track(target, key) {
// If activeEffect is null, the following is not executed
// This is to avoid track being triggered by things like console.log(person.name)
if(! activeEffect)return
let depsMap = targetMap.get(target)
if(! depsMap) { targetMap.set(target, depsMap =new Map()}let dep = depsMap.get(key)
if(! dep) { depsMap.set(key, dep =new Set())
}
dep.add(activeEffect) // Add the activeEffect
}
// Each effect function is executed this way
effect(effectNameStr1)
effect(effectNameStr2)
effect(effectAgeStr1)
effect(effectAgeStr2)
effect(effectTypeStr1)
effect(effectTypeStr2)
effect(effectHeightStr1)
effect(effectHeightStr2)
Copy the code
Realize the ref
This is how we use ref in Vue3
let num = ref(5)
console.log(num.value) / / 5
Copy the code
Num then becomes a reactive data, and num. Value is written this way to use num
It’s very easy to implement a REF, because we’ve already implemented Reactive, so you just need to do this
function ref (initValue) {
return reactive({
value: initValue
})
}
Copy the code
Let’s try it out. How does it look
let num = ref(5)
effect(() = > sum = num.value * 100)
console.log(sum) / / 500
num.value = 10
console.log(sum) / / 1000
Copy the code
To realize the computed
So let’s do computed, which is really easy, by the way
function computed(fn) {
const result = ref()
effect(() = > result.value = fn()) // Executes a computed passed function
return result
}
Copy the code
Let’s look at the results
let num1 = ref(5)
let num2 = ref(8)
let sum1 = computed(() = > num1.value * num2.value)
let sum2 = computed(() = > sum1.value * 10)
console.log(sum1.value) / / 40
console.log(sum2.value) / / 400
num1.value = 10
console.log(sum1.value) / / 80
console.log(sum2.value) / / 800
num2.value = 16
console.log(sum1.value) / / 160
console.log(sum2.value) / / 1600
Copy the code
Since then we have implemented all the functions of this article
The final code
const targetMap = new WeakMap(a)function track(target, key) {
// If activeEffect is null, the following is not executed
// This is to avoid track being triggered by things like console.log(person.name)
if(! activeEffect)return
let depsMap = targetMap.get(target)
if(! depsMap) { targetMap.set(target, depsMap =new Map()}let dep = depsMap.get(key)
if(! dep) { depsMap.set(key, dep =new Set())
}
dep.add(activeEffect) // Add the activeEffect
}
function trigger(target, key) {
let depsMap = targetMap.get(target)
if (depsMap) {
const dep = depsMap.get(key)
if (dep) {
dep.forEach(effect= > effect())
}
}
}
function reactive(target) {
const handler = {
get(target, key, receiver) {
track(receiver, key) // Collect dependencies while accessing
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
trigger(receiver, key) // Automatically notifies updates when setting the value}}return new Proxy(target, handler)
}
let activeEffect = null
function effect(fn) {
activeEffect = fn
activeEffect()
activeEffect = null
}
function ref(initValue) {
return reactive({
value: initValue
})
}
function computed(fn) {
const result = ref()
effect(() = > result.value = fn())
return result
}
Copy the code
The Proxy and Reflect
Proxy
const person = { name: 'Lin Three Hearts'.age: 22 }
const proxyPerson = new Proxy(person, {
get(target, key, receiver) {
console.log(target) // The original person
console.log(key) / / the property name
console.log(receiver) // proxyPerson after proxy
},
set(target, key, value, receiver) {
console.log(target) // The original person
console.log(key) / / the property name
console.log(value) // Set the value
console.log(receiver) // proxyPerson after proxy
}
})
proxyPerson.name // Access attributes trigger get methods
proxyPerson.name = 'sunshine_lin' // Set the property value to trigger the set method
Copy the code
Reflect
Here are two methods for Reflecting
get(target, key, receiver)
: Personal understanding is, visittarget
thekey
Property, butthis
Is pointing toreceiver
, so the value actually accessed isThe receiver of the key
But this is not direct accessreceiver[key]
Properties, you have to distinguish between themset(target, key, value, receiver)
: Personal understanding is, settingtarget
thekey
Properties forvalue
, butthis
Is pointing toreceiver
“, so it’s actually settingThe receiver of the key
The value ofvalue
But this is not directreceiver[key] = value
You have to differentiate
Receiver [key] = value; receiver[key] = value; reflect. get; reflect. set Let’s take a counter example
const person = { name: 'Lin Three Hearts'.age: 22 }
const proxyPerson = new Proxy(person, {
get(target, key, receiver) {
return Reflect.get(receiver, key) // Equivalent to receiver[key]
},
set(target, key, value, receiver) {
Reflect.set(receiver, key, value) // Equivalent to receiver[key] = value}})console.log(proxyPerson.name)
proxyPerson.name = 'sunshine_lin'
// The stack memory exceeds the Maximum call stack size exceeded
Copy the code
Why is that? Take a look at the solution below
Now you can see why you cannot directly receiver[key] or receiver[key] = value, because doing so will cause an infinite loop and eventually an error. So the right thing to do is
const person = { name: 'Lin Three Hearts'.age: 22 }
const proxyPerson = new Proxy(person, {
get(target, key, receiver) {
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
}
})
console.log(proxyPerson.name) / / Lin three hearts
proxyPerson.name = 'sunshine_lin'
console.log(proxyPerson.name) // sunshine_lin
Copy the code
I’m sure some of you are going to ask, you can write it this way, why not? Let me put it down here
const proxyPerson = new Proxy(person, {
get(target, key, receiver) {
return Reflect.get(target, key)
},
set(target, key, value, receiver) {
Reflect.get(target, key, value)
}
})
Copy the code
Why do we use them together
It’s also possible to Reflect without Proxy. We could write it this way, and still get what we want
const person = { name: 'Lin Three Hearts'.age: 22 }
const proxyPerson = new Proxy(person, {
get(target, key, receiver) {
return target[key]
},
set(target, key, value, receiver) {
target[key] = value
}
})
console.log(proxyPerson.name) / / Lin three hearts
proxyPerson.name = 'sunshine_lin'
console.log(proxyPerson.name) // sunshine_lin
Copy the code
So why is Proxy and Reflect recommended? Because the Proxy and Reflect methods are one-to-one, using Reflect in a Proxy improves semantics
The Proxy of the get
The correspondingReflect.get
The Proxy of the set
The correspondingReflect.set
- There are a lot of other ways that I’m not going to list, but they’re all one to one
Another reason is to try to put this on the receiver rather than the target
Why try to put this on the proxy object receiver instead of the original object Target? The target object may also be a proxy object of another proxy, so if this is always placed on target, the probability of a bug will be greatly increased.
const proxyPerson = new Proxy(person, {
get(target, key, receiver) {
return Reflect.get(target, key)
},
set(target, key, value, receiver) {
Reflect.get(target, key, value)
}
})
Copy the code
conclusion
If you think this article is a little bit helpful to you, click a like and encourage Lin Sanxin haha.
To enter the learning group, touch fish, please click here to touch fish