The responsivity principle of VUE3
Do the response:
// let vdata = reactive(data)Copy the code
The difference between vue2 and VUe3 is as follows:
1. Vue2 (dynamically adding and deleting attributes does not work)
2, arrays,
3. Initializing deep recursion is slow
4. The new data structure does not support Map and SET
About using the Proxy class
How does the following function work first
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
const val = Reflect.get(obj, key)
return typeof val === 'object' ? reactive(val) : val
},
set(target, key, val) {
// console.log(`set: ${key}`)
const ret = Reflect.set(target, key, val)
return ret
},
deleteProperty(target, key) {
// console.log(`delete: ${key}`)
return Reflect.deleteProperty(target, key)
},
})
}
const state = reactive({
msg: 'hello world'.obj: { msg: 10 },
})
state.msg
state.foo = 'hello hui'
delete state.msg
console.log(state.msg)
console.log(state.obj.msg)
// get: msg
// set: foo
// delete: msg
// get: msg
// undefined
// get: obj
// get: msg
/ / 10
Copy the code
About reactive code implementation
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
const val = Reflect.get(target, key)
track(target, key)
return typeof val === 'object' ? reactive(val) : val
},
set(target, key, val) {
// console.log(`set: ${key}`)
/ / start the trigger
const ret = Reflect.set(target, key, val)
trigger(target, key)
return ret
},
deleteProperty(target, key) {
// console.log(`delete: ${key}`)
trigger(target, key)
return Reflect.deleteProperty(target, key)
},
})
}
const effectStack = []
/ / map
const targetMap = new WeakMap(a)function effect(fn) {
const e = createReactiveEffect(fn)
// Perform an immediate processing error into the effectStack
e()
return e
}
function createReactiveEffect(fn) {
const effect = function () {
try {
effectStack.push(effect) / / in the
return fn() / / execution
} finally {
effectStack.pop()
}
}
return effect
}
Weekmap (object mapping to obtain map) map(key value mapping set) Set collects effect events
function track(target, key) {
// Try to get the effect function
const effect = effectStack[effectStack.length - 1] // take the last one
if (effect) {
let depMap = targetMap.get(target) / / get the map
if(! depMap) {// If not, collect it for the first time
depMap = new Map()
targetMap.set(target, depMap) // Insert targetMap if it doesn't exist
}
let deps = depMap.get(key) / / get the set
if(! deps) { deps =new Set()
depMap.set(key, deps)
}
deps.add(effect) // Collect dependencies}}// Dependency triggers
function trigger(target, key) {
let depMap = targetMap.get(target) / / get the map
if (depMap) {
let deps = depMap.get(key)
deps.forEach((fn) = > {
fn()
})
}
}
Copy the code
The demo test:
const state = reactive({
msg: 'hello world',
obj: { msg: 10 },
})
effect(() => {
state.msg
console.log(state.msg)
})
state.msg = 'hello boy'
Copy the code
HTML test:
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, Initial scale=1.0" /> <title>Document</title> </head> <body> <div id="app"> <div id="title"></div> </div> <script src="./index.js"></script> <script> const data = reactive({ title: }) const dom = document.getelementById ('title') effect(() => {dom.textContent = data.title}) setInterval(() => { data.title = new Date().toString() }, 1000) </script> </body> </html>Copy the code
The Run-time code module understands watch and computed implementations