手摸手学习vue3源码三:ref

87 阅读1分钟
  • 文件目录:packages/reactivity/src/ref.ts
  • 核心函数:createRef
  • 解读:使用的时候,通过 xxx.value取值, xxx.value=aaa赋值。优点:可以直接赋值value,可以重新定义对象的响应式属性,而且也会触发依赖更新,重新收集新对象的依赖
function createRef(rawValue, shallow) {
    // 如果是ref创建的值,直接返回
    if (isRef(rawValue)) {
        return rawValue
    }
    // 否则,通过RefImpl创建
    return new RefImpl(rawValue, shallow)
}
  • 核心类 RefImpl
// RefImpl中定义了get value和set value 操作符,这就要求通过ref定义的响应式数据,取值和赋值的时候,需要 xxx.value 进行操作
class RefImpl {

    constructor(value, isShallow) {
        this._rawValue = isShallow ? value : toRaw(value)
        this._value = isShallow ? value : toReactive(value)
    }

    get value() {
       
        track() // 取值函数
        // 在template渲染目标时,就会取值value,顺便收集更改渲染函数作为依赖
        return this._value
    }
    set value(newValue) {
        // 执行value值进行替换时,触发set操作符,会重新执行toReactive(newVal),重新定义值的响应式属性
        const useDirectValue = this[ReactiveFlags.IS_SHALLOW] || isShallow(newValue) || isReadonly(newValue)
        
        newValue = useDirectValue ? newValue : toRaw(newValue)
        this.value = useDirectValue ? newValue : toReactive(newValue)
        
        if (hasChanged(newVal, this._rawValue)) {
            this._rawValue = newVal
            this._value = useDirectValue ? newVal : toReactive(newVal)
            // 赋值函数
            trigger(this, newVal)
        }
    }
}
  • toReactive
function toReactive(value) {
    isObject(value) ? reactive(value) : value
}