Skip to content

响应式原理

响应系统是 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 函数,我们称之为副作用函数,副作用函数指的是会产生副作用的函数。函数的执行会直接或者间接影响 其他函数的执行。

当修改 objx 的值, sum 的值并不会跟着变, 要手动执行一次 effect 函数才能重新得到新的 sum 的值,假如我们能 实现当 objx 或者 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)
}