响应性基础
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]
}
网友评论