feat(ref): 实现 ref 值变化检测和依赖触发功能
- 在 shared 包中新增 hasChanged 函数用于比较值是否发生变化 - 修改 RefImpl 类添加 _rawValue 属性存储原始值 - 实现 ref setter 中的值变化检测逻辑 - 添加 triggerRefValue 函数用于触发 ref 依赖更新 - 优化 ref 的 getter 和 setter 方法实现响应式更新
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { createDep, Dep } from './dep'
|
||||
import { toReactive } from './reactive'
|
||||
import { activeEffect, track, trackEffects } from './effect'
|
||||
import { activeEffect, triggerEffects, trackEffects } from './effect'
|
||||
import { hasChanged } from '@vue/shared'
|
||||
|
||||
export interface Ref<T = any> {
|
||||
value: T
|
||||
@@ -17,20 +18,36 @@ function createRef(rawValue: unknown, shallow: boolean) {
|
||||
}
|
||||
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
|
||||
) {
|
||||
this._rawValue = value
|
||||
this._value = __v_isShallow ? value : toReactive(value)
|
||||
}
|
||||
get value() {
|
||||
trackRefValue(this)
|
||||
return this._value
|
||||
}
|
||||
set value(newValue) {}
|
||||
set value(newValue) {
|
||||
if (hasChanged(newValue, this._rawValue)) {
|
||||
this._rawValue = newValue
|
||||
this._value = toReactive(newValue)
|
||||
triggerRefValue(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
//触发依赖
|
||||
export function triggerRefValue(ref) {
|
||||
if (ref.dep) {
|
||||
triggerEffects(ref.dep)
|
||||
}
|
||||
}
|
||||
|
||||
//收集依赖
|
||||
export function trackRefValue(ref) {
|
||||
if (activeEffect) {
|
||||
trackEffects(ref.dep || (ref.dep = createDep()))
|
||||
|
||||
@@ -3,3 +3,11 @@ export const isArray = Array.isArray
|
||||
|
||||
export const isObject = (val: unknown) =>
|
||||
val !== null && typeof val === 'object'
|
||||
|
||||
/**
|
||||
* 对比两个数据是否发生改变
|
||||
* @param value
|
||||
* @param oldValue
|
||||
*/
|
||||
export const hasChanged = (value: any, oldValue: any): boolean =>
|
||||
!Object.is(value, oldValue)
|
||||
|
||||
Reference in New Issue
Block a user