响应式原理
响应系统是 vue.js 的重要组成部分
响应式数据和副作用函数
javascript
let obj = { x: 1, y: 2 }
let sum
function effect() {
sum = obj.x + obj.y
}
effect()
console.log(sum) // 3
obj.x = 2
console.log(sum) // 仍然是3像上面代码中的 effect 函数,我们称之为副作用函数,副作用函数指的是会产生副作用的函数。函数的执行会直接或者间接影响 其他函数的执行。
当修改 obj 中 x 的值, sum 的值并不会跟着变, 要手动执行一次 effect 函数才能重新得到新的 sum 的值,假如我们能 实现当 obj 中 x 或者 y 更改后,能自动运行 effect 的函数得到最新的 sum,我们就称对象 obj 为响应式数据。
响应式数据基本实现
实现响应式数据关键是拦截对象属性的读取和设置操作,在 ES2015 之前,我们只能通过 Object.defineProperty 来实现,这也是 Vue.js 2 所采用的方式。在 ES2015+ 中,我们可以使用代理对象 Proxy 来实现,这也是 Vue.js 3 所采用的方式。
javascript
// 存储副作用的桶
const bucket = new Set()
const data = { x: 1, y: 2 }
const obj = new Proxy(data, {
get(target, key) {
// 将副作用函数添加到桶中
bucket.add(effect)
return target[key]
},
set(target, key, newVal) {
target[key] = newVal
// 把桶中的副作用函数取出执行
bucket.forEach((fn) => fn())
// 返回 true 表示设置操作成功
return true
},
})
function effect() {
console.log(obj.x + obj.y)
}