vue3-源码理解shallowRef和shallowReactive浅响应式
1.什么叫浅响应式?
响应式:vue3中有ref和reactive两个方法,可以把数据变成响应式数据,响应式简单来讲就是能监测到数据得变化,从而去更新视图,使用ref和reactive创建得数据不管它得层级有多深,只要改变都能监测到。
例如:
const person = ref({
name:'zs',
age:48,
Child:{
name:'lisi',
age:18
}
})
// 这种修改是能被监测到得,并能成功触发视图更新
person.value.Child.age = 20;
浅响应式:即只监测浅层数据得改变而不监测生成数据得改变,即只有最顶层数据得改变才能被监测到
2.shallowRef
shallowRef是ref得浅层响应,使用shallowRef创建得数据只有根级别得才是响应式得,即使使用能使用value直接修改得才是响应式得
例如:
const person = shallowRef({
name:'zs',
age:48,
Child:{
name:'lisi',
age:18
}
})
// 这种修改能成功修改Child.age得值,但是此时得修改没有被监测到,所以不能触发视图更新
person.value.Child.age = 20;
//如果想修改得同时更新视图,则需要如下修改
person.value = {
name:'zs',
age:48,
Child:{
name:'lisi',
age:20
}
}
如果是一个普通类型得数据shallowRef和ref并没有区别,如:
const count = shallowRef(12);
count.value++
shallowRef源码解析:
1.
export function shallowRef(value?: unknown) {
//调用shallowRef方法时,实际调用得是createRef方法
//value:传入得目标数据,true:表示是shallow方法
return createRef(value, true)
}
2.
function createRef(rawValue: unknown, shallow: boolean) {
//如果已经是ref响应式,则直接返回
if (isRef(rawValue)) {
return rawValue
}
//否则使用构造函数创建ref对象
return new RefImpl(rawValue, shallow)
}
3.
class RefImpl<T> {
private _value: T
private _rawValue: T
public dep?: Dep = undefined
public readonly __v_isRef = true
constructor(value: T, public readonly __v_isShallow: boolean) {
//关键点在这里:__v_isShallow这个参数如果为false,则调用toReactive,而shallowRef方法中,该参数为true,则故能调用该方法处理传入得目标数据
this._rawValue = __v_isShallow ? value : toRaw(value)
this._value = __v_isShallow ? value : toReactive(value)
}
get value() {
trackRefValue(this)
return this._value
}
set value(newVal) {
const useDirectValue =
this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)
newVal = useDirectValue ? newVal : toRaw(newVal)
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal
this._value = useDirectValue ? newVal : toReactive(newVal)
triggerRefValue(this, newVal)
}
}
}
toReactive:
export const toReactive = <T extends unknown>(value: T): T =>
//如果是object,则调用reactive
isObject(value) ? reactive(value) : value
//最终走到这里
function createReactiveObject(
target: Target,
isReadonly: boolean,
baseHandlers: ProxyHandler<any>,
collectionHandlers: ProxyHandler<any>,
proxyMap: WeakMap<Target, any>
) {
if (!isObject(target)) {
if (__DEV__) {
console.warn(`value cannot be made reactive: ${String(target)}`)
}
return target
}
// target is already a Proxy, return it.
// exception: calling readonly() on a reactive object
if (
target[ReactiveFlags.RAW] &&
!(isReadonly && target[ReactiveFlags.IS_REACTIVE])
) {
return target
}
// target already has corresponding Proxy
const existingProxy = proxyMap.get(target)
if (existingProxy) {
return existingProxy
}
// only specific value types can be observed.
const targetType = getTargetType(target)
if (targetType === TargetType.INVALID) {
return target
}
//重点:使用proxy代理传入得目标对象,此后该对象得任何更改都会被监测到
const proxy = new Proxy(
target,
targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
)
proxyMap.set(target, proxy)
return proxy
}
3.shallowReactive
shallowReactive是reactive得浅响应式,和shallowRef一样只有根级别数据是响应式得
const person = reactive({
name:'zs',
age:48,
Child:{
name:'lisi',
age:18
}
})
// 根级别属是响应式得,修改后能触发视图更新
person.name = '张三';
// 更深层次得数据更新,不能监测到,不能触发视图更新
person.Child.age = 20;
shallowReactive源码解析:


浙公网安备 33010602011771号