ref
接受一个内部值并返回一个响应式且可变的 ref
对象。ref
对象具有指向内部值的单个 property.value
。
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
ref实现原理
ref的原理就是将一个普通值,转化成对象,并且在获取和设置值时可以增加依赖收集和触发更新的功能
function ref(value){
return createRef(value)
}
function convert(rawValue){
return isObject(rawValue) ? reactive(rawValue) : rawValue
}
function createRef(value, shallow = false){
return new RefImpl(value, shallow)
}
class RefImpl{
_value;
__v_isRef = true // flag 表示这是一个ref
constructor(rawValue,shallow){
this.rawValue = rawValue;
this.shallow = shallow;
this._value = shallow ? rawValue : convert(rawValue)
}
get value(){
// 取值的时候收集依赖
track(this, 'get', 'value')
return this._value
}
set(newValue){
if(hasChange(newValue, this.rawValue)){
this.rawValue = newValue;
this._value = this.shallow ? newValue : convert(newValue)
// 设置值的时候触发依赖更新
trigger(this, 'set', 'value', newValue)
}
}
}
unref
如果参数是一个 ref
,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val
的语法糖函数
function useFoo(x: number | Ref<number>) {
const unwrapped = unref(x) // unwrapped 现在一定是数字类型
}
toRef
可以用来为源响应式对象上的某个 property
新创建一个 ref
。然后,ref
可以被传递,它会保持对其源 property
的响应式连接。
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) // 2
state.foo++
console.log(fooRef.value) // 3
当你要将 prop
的 ref
传递给复合函数时,toRef
很有用:
export default {
setup(props) {
useSomeFeature(toRef(props, 'foo'))
}
}
即使源 property
不存在,toRef
也会返回一个可用的 ref
。这使得它在使用可选 prop
时特别有用,可选 prop
并不会被 toRefs
处理。
toRef实现原理
toRef 只能将响应式对象的某个属性转换为ref,普通对象,没有响应式
class ObjectRefImpl {
__v_isRef = true;
constructor(target, key) {
this.target = target;
this.key = key
}
get value() {
return this.target[this.key];
}
set value(newValue) {
this.target[this.key] = newValue
}
}
function toRef(target, key) {
return isRef(object[key]) ? object[key] : new ObjectRefImpl(target, key)
}
toRefs
将响应式对象转换为普通对象,其中结果对象的每个 property
都是指向原始对象相应 property
的 ref
。
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
/*
stateAsRefs 的类型:
{
foo: Ref<number>,
bar: Ref<number>
}
*/
// ref 和原始 property 已经“链接”起来了
state.foo++
console.log(stateAsRefs.foo.value) // 2
stateAsRefs.foo.value++
console.log(state.foo) // 3
function toRefs() {
if (__DEV__ && !isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`)
}
const ret: any = isArray(object) ? new Array(object.length) : {}
for (const key in object) {
ret[key] = toRef(object, key)
}
return ret
}
标签:
Vue
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性