zoukankan      html  css  js  c++  java
  • shallowReactive与reactive的原理浅析

    vue3中的shallowReactive与reactive是怎么实现的呢?学习自尚硅谷

    目的

    使一个正常的object对象转化为响应式对象

    解决方案

    简单的说,就是w3c在object的增删改查时增加了hook函数,可以让用户对原生js获取事件、赋值事件等进行捕捉。这个hook函数就是ProxyReflect.
    我接下来做的一件事就是使用这个hook函数,来使一个正常的object对象转化为响应式对象。

    严格来讲,这个最后结果还不是响应式对象,只是这个object再增删改查属性的时候会触发自定义逻辑,具体编写什么样的逻辑能能够做到vue3中的响应式,本文没有阐述。

    可以首先定义一个事件处理函数,对原生js获取事件、赋值事件等进行捕捉,随后再传递给Reflect

    const reactiveHandler = {
      get (target, key) {
    
        if (key==='_is_reactive') return true
        console.log('数据已获取');
    
        return Reflect.get(target, key)
      },
    
      set (target, key, value) {
        const result = Reflect.set(target, key, value)
        console.log('数据已更新, 去更新界面')
        return result
      },
    
      deleteProperty (target, key) {
        const result = Reflect.deleteProperty(target, key)
        console.log('数据已删除, 去更新界面')
        return result
      },
    }
    

    然后就可以进行转化了:

    /* 
    自定义shallowReactive
    目的是让该对象成为一个Proxy对象,方便对一些增删改查的方法进行拦截并添加自定义逻辑
    */
    function shallowReactive(obj) {
      return new Proxy(obj, reactiveHandler)
    }
    
    /* 
    自定义reactive
    目的是让该对象,以及该对象内部所有object类型的成员成为一个Proxy对象,方便对一些增删改查的方法进行拦截并添加自定义逻辑
    */
    function reactive (target) {
      if (target && typeof target==='object') {
        // 内部代码块的作用是:
          // 1. 遍历子元素,目的是查看子元素中是否存在object,如果存在再次进入子元素;
          // 2. 最终返回一个代理对象Proxy,代理该object
    
        if (target instanceof Array) { 
    
          // 检测到是数组
          target.forEach((item, index) => {
            target[index] = reactive(item)
          })
    
        } else { 
    
          // 检测到是对象
          Object.keys(target).forEach(key => {
            target[key] = reactive(target[key])
          })
    
        }
        // 如果这个taraget是一个object,下面的代码是无论如何都会对这个object执行的
        // 换句话说:对每一个子object类型的对象,执行了下面的代码
        const proxy = new Proxy(target, reactiveHandler)
        return proxy
      }
    
      // 如果不是object,则直接返回
      return target
    }
    
    
    
    
    
    
    
    console.log('=================测试自定义shallowReactive');
    const proxy = shallowReactive({
      a: {
        b: 3
      }
    })
    
    proxy.a = {b: 4} // 劫持到了
    proxy.a.b = 5 // 没有劫持到
    
    console.log('=================测试自定义reactive');
    /* 测试自定义reactive */
    const obj = {
      a: 'abc',
      b: [{x: 1}],
      c: {x: [11]},
    }
    
    const proxy2 = reactive(obj)
    console.log(proxy2)
    proxy2.b[0].x += 1
    proxy2.c.x[0] += 1
    
    
  • 相关阅读:
    常见ETL工具一览
    php语言查询Mysql数据库内容
    修改博客园模板样式
    《将博客搬至CSDN》
    使用 Git 和 GitHub 托管项目源码
    Delphi webbrowser 的一些方法
    Delphi 实现 图灵机器人API(IDHTTP POST )
    Delphi 中调用JS文件中的方法
    HTTP 常见异常状态及Delphi IDHTTP 控件处理方式
    Delphi Cookie获取及使用
  • 原文地址:https://www.cnblogs.com/lyzz1314/p/14812191.html
Copyright © 2011-2022 走看看