美文网首页
深入响应式系统

深入响应式系统

作者: skoll | 来源:发表于2023-04-02 00:16 被阅读0次

    响应性基础

    let A0 = 1
    let A1 = 2
    let A2 = A0 + A1
    
    console.log(A2) // 3
    
    A0 = 2
    console.log(A2) // 仍然是 3
    
    

    1 .如何改变A0,让A2自动更新

    1 .将运算包装为一个函数
    2 .当A0,A1发生变化的时候,重新运算这个函数
    3 .在react里面就是这样便是
    useEffect(()=>{
      let a2=a1+a0
    },[a1,a0])
    4 .需要一个魔法函数,能够在A0,A1这两个依赖变化的时候调用update
    

    Vue中的响应性是如何工作的

    1 .js中无法追踪局部变量的读写,原生js没有提供任何机制能做到这一点,但是对象的属性是可以追溯到的
    2 .这又是一个缺点:功能的实现必须依赖于语法支持.

    const count = signal(0)
    
    count() // access the value
    count.set(1) // set new value
    count.update((v) => v + 1) // update based on previous value
    
    // mutate deep objects with same identity
    const state = signal({ count: 0 })
    state.mutate((o) => {
      o.count++
    })
    
    //为啥不像这个,自己实现更新函数呢
    

    3 .劫持属性的两种方式

    1 .getter,setters
    function ref(value) {
      const refObject = {
        get value() {
          track(refObject, 'value')
          return value
        },
        set value(newValue) {
          value = newValue
          trigger(refObject, 'value')
        }
      }
      return refObject
    }
    
    function reactive(obj) {
      return new Proxy(obj, {
        get(target, key) {
          track(target, key)
          return target[key]
        },
        set(target, key, value) {
          target[key] = value
          trigger(target, key)
        }
      })
    }
    //track 内部,检查当前是否有正在运行的副作用,如果有,我们会查找到一个存储了所有追踪该属性的订阅者的Set,然后将这个副作用作为新订阅者添加到Set中
    
    //teigger 内部,我们会再次查找到该属性的所有订阅副作用。这一次我们要执行这些副作用
    

    组件调试钩子

    1 .当你想要知道正在追踪什么,哪些属性发生了变化,并导致了组件重新渲染
    2 .onRenderTracked ,可以看到哪些依赖正在被属性
    3 .onenenderTriggered(),哪些依赖正在触发更新

    <script setup>
    import { onRenderTracked, onRenderTriggered } from 'vue'
    
    onRenderTracked((event) => {
      debugger
    })
    
    onRenderTriggered((event) => {
      debugger
    })
    </script>
    //这些钩子只会在开发模式工作
    

    计算属性调试,watch 也有,之前一般都是直接console

    1 .computed钩子也支持第二个参数传入两个回调函数

    const plusOne = computed(() => count.value + 1, {
      onTrack(e) {
        // 当 count.value 被追踪为依赖时触发
        debugger
      },
      onTrigger(e) {
        // 当 count.value 被更改时触发
        debugger
      }
    })
    
    // 访问 plusOne,会触发 onTrack
    console.log(plusOne.value)
    
    // 更改 count.value,应该会触发 onTrigger
    count.value++
    
    

    与外部状态系统集成

    1 .Vue的响应系统是通过深度转换普通js对象为响应式代理来实现的。
    2 .这种深度转换在一些情况下不是必要的,在和一些外部状态管理系统集成时,甚至是需要避免的。如果另一个解决方案也使用了Proxy

    3 .思路如下:将外部状态放在一个 shallowRef 中。一个浅层的 ref 中只有它的 .value 属性本身被访问时才是有响应性的,而不关心它内部的值。当外部状态改变时,替换此 ref 的 .value 才会触发更新。

    不可变数据

    1 .如果想要实现撤销,重做功能,需要对用户编辑的状态做快照记录。
    2 .如果状态树很大的话,Vue的可变响应系统没法很好的处理这种情况。
    3 .需要用不可变数据结构来实现。比如Immer 来搭配Vue

    import produce from 'immer'
    import { shallowRef } from 'vue'
    
    export function useImmer(baseState) {
      const state = shallowRef(baseState)
      const update = (updater) => {
        state.value = produce(state.value, updater)
      }
    
      return [state, update]
    }
    
    

    相关文章

      网友评论

          本文标题:深入响应式系统

          本文链接:https://www.haomeiwen.com/subject/hvelddtx.html