思路

  1. 保存未来执行修改的代码(effect)。
  2. 监测值的改变
    1. 使用proxy 对象实现
  3. 值改变后,执行 trigger effect

    监测值的改变

    ```typescript const person = { name: ‘Jone’ } const handler = { // 目标对象,属性名,代理对象 get(target, prop, receiver) { console.log(‘trigger get’, target, prop) return target[prop] }, // 目标对象,属性名,要填入的值,代理对象 set(target, prop, value, receiver) { console.log(‘trigger set’, target, prop, value) target[prop] = value return true // 告诉设置成功 } } const proxy = new Proxy(person, handler)

proxy.name = ‘111’

  1. 使用` Reflect `对象上的静态方法改写:
  2. ```typescript
  3. console.log(Reflect.get(person, 'name'))
  4. console.log(Reflect.set(person, 'name','maomao'))
  5. console.log(Reflect.get(person, 'name'))
  1. const person = {
  2. name: 'Jone'
  3. }
  4. const handler = {
  5. get() {
  6. console.log('trigger get')
  7. return Reflect.get(...arguments) // Reflect.get() 接收的参数和 handler.get 接收的参数一样
  8. },
  9. set() {
  10. console.log('trigger set')
  11. return Reflect.set(...arguments) // Reflect.set() 接收的参数和 handler.set 接收的参数一样
  12. }
  13. }
  14. const proxy = new Proxy(person, handler)
  15. proxy.name = '111'

存储和触发 effect

  • 将所有 effect 加入特定的数据结构
  • 创建特定的函数可以再次运行这些 effect
  • 使用 Proxygettersetter,将这些函数放入对应的位置

原生示例:

  1. let product = { price: 5, count: 2 }
  2. let total = 0
  3. let effect = () => {
  4. total = product.price * product.count
  5. }
  6. effect()
  7. console.log(total);
  8. product.price = 10
  9. effect()
  10. console.log(`total is ${total}`);
  1. let product = { price: 5, count: 2 }
  2. let total = 0
  3. let dep = new Set()
  4. // 将所有 effect 加入特定的数据结构
  5. function track() {
  6. dep.add(effect)
  7. }
  8. // 创建特定的函数可以再次运行这些 effect
  9. function trigger() {
  10. dep.forEach(effect => effect());
  11. }
  12. let effect = () => {
  13. total = product.price * product.count
  14. }
  15. effect()
  16. console.log(total);
  17. track()
  18. product.price = 10
  19. trigger()
  20. console.log(`total is ${total}`);

Proxy响应式封装

  • get的时候触发收集effect
  • set的时候触发effect执行 ```typescript

let total = 0 let dep = new Set() // 存储effect function track() { dep.add(effect) } // 遍历执行effect function trigger() { dep.forEach(effect => effect()); } // 响应式封装 const reactive = (obj) => { const handler = { get() { let result = Reflect.get(…arguments) track() return result }, set() { let result = Reflect.set(…arguments) trigger() return result } } return new Proxy(obj, handler) } let effect = () => { total = product.price * product.count } const product = reactive({ price: 5, count: 2 }) effect() console.log(total); product.price = 10 console.log(total is ${total}); ```