6.vue3中ref的实现原理

问也去 2022-06-23 15:09:21 阅读数:625

vue原理实现ref6.vue3

Vue3中ref的实现原理

ref基本使用

ref可以使普通值转换为响应式的对象


const {
 effect, reactive, computed, watch,ref } = Vue;
const state = reactive({

name:'s',
age:13
})
let flag = ref(false)
effect(()=>{

app.innerHTML = flag.value
})
setTimeout(()=>{

flag.value = true
},1000)

ref相关实现

  • ref实际就是对一个普通值做了一层包装,包装成一个对象,并通过其get和set实现依赖收集和更新,其实现原理类似于computed
import {
 isObject } from "@vue/shared";
import {
 reactive } from "./reactive";
import {
 activeEffect, trackEffects, triggerEffects } from "./effect";
export function ref(value){

return new RefImpl(value);
}
class RefImpl {

private _value = null;
private __v_isRef = true;
private dep = null;
constructor(public rawValue){

this._value = toReactive(rawValue)
}
get value(){

if(activeEffect){

trackEffects(this.dep ||(this.dep = new Set()))
}
return this._value
}
set value(newValue){

if(newValue !== this.rawValue){

this._value = toReactive(newValue)
this.rawValue = newValue
triggerEffects(this.dep)
}
}
}
export function toReactive(value){

return isObject(value) ? reactive(value):value
}
  • 其中有一个toRef函数,可以解析proxy对象,对单个属性形成响应式
 const {
 effect, reactive, computed, watch,ref,toRef } = Vue;
const state = reactive({

name:'s',
age:13
})
let name = toRef(state,'name')
effect(()=>{

app.innerHTML = name.value
})
setTimeout(()=>{

name.value = 'xx'
},1000)

其实现原理是利用get和set,当访问属性的value时,返回object[key].value

export function toRef(object,key){

return new ObjectRefImpl(object,key)
}
class ObjectRefImpl{

private __v_isRef = true;
private _value = null;
constructor(public object,public key){

}
get value(){

return this.object[this.key]
}
set value(newValue){

this.object[this.key] = newValue
}
}
  • 同理 toRefs函数可以对proxy对象的所有属性进行响应式
 const {
 effect, reactive, computed, watch,ref,toRef,toRefs } = Vue;
const state = reactive({

name:'s',
age:13
})
let {
name,age }= toRefs(state)
effect(()=>{

app.innerHTML = name.value + age.value
})
setTimeout(()=>{

name.value = 'xx'
},1000)
  • 通过toRefs可以直接通过属性.value进行访问,但是每次访问加上value,未免太过麻烦,有什么办法可以直接访问属性吗?proxyRefs可以实现这个需求
export function proxyRefs(object){

return new Proxy(object,{

get(target,key,receiver){

let r = Reflect.get(target,key,receiver)
return r.__v_isRef?r.value:r
},
set(target,key,value,receiver){

if(target[key].__v_isRef ){

target[key].value = value
return true
}
return Reflect.set(target,key,value,receiver)
}
})
}
版权声明:本文为[问也去]所创,转载请带上原文链接,感谢。 https://blog.csdn.net/wenyeqv/article/details/125397911