vue设计与实现 第6章 ref 响应原理 笔记
2024-09-18 14:26:20
ref 函数实现代码
const a = ref(1);
function ref(value){
const wrapper = {value}
Object.defineProperty(wrapper,'__v_isRef',{
value: true
})
return reactive(wrapper)
}
把新建一个对象,value 属性是原始值,再把对象交给 reactive 进行响应式处理。所以要获取 ref 的值要拿取其 value 属性。 这里还添加了 不可遍历、配置、改写的属性 __v_isRef。标识 ref 类型。
ref 还能够用于响应式丢失问题
解构和展开运算符 会让响应式数据失去响应 下面是例子
const obj = reactive({ foo: 1, bar: 2 });
let { foo, bar } = obj;
const target = {
...obj,
};
foo = 123;
target.foo = 2;
console.log(obj); const a = ref(1);
let { value } = a;
value = 456;
console.log(a);
打印结果可以看出,解构和展开的属性已经没了和原来的响应式数据的联系,如何继续保持这种联系呢? 可用 toRef 和 toRefs API
toRef 代码实现
function toRef(target,key){
const wrapper = {
get value(){
return Reflect.get(target,key)
},
set value(newvalue){
return Reflect.set(target,key,newvalue)
}
}
Object.defineProperty(wrapper,'__v_isRef',{
value: true
})
return wrapper
}
toRef 就是把对象的某个属性转为 ref 。实现和 ref 函数差不多,只不过 ref 是把新建的对象 交给 reactive 。
而 toRef 是改写新建的对象的 value 属性的 get 方法和 set 方法,关联上目标对象属性。
toRefs 代码实现
function toRefs(target){
const wrapper = {}
for (let key in target) {
wrapper[key] = toRef(target,key);
}return wrapper
}
toRefs 只是循环目标对象属性,调用 toRef
现在又有了新的问题,虽然把响应式丢失解决了,但是必须通过 value属性 才能访问,例子
const obj = reactive({ foo: 1, bar: 2 });
const target = {...toRefs(obj)};
target.foo.value
解决方案,创建一个代理对象,每次取值时是 ref 类型,返回 value 属性
function proxyRefs(target){
return new Proxy(target,{
get (target,key,receiver) {
const res = Reflect.get(target,key,receiver);
return res.__v_isRef ? res.value:res
},
set (target,key,newVal,receiver){
if(target[key].__v_isRef) {
Reflect.set(target[key],value,newVal,receiver)
return true
}
return Reflect.set(target,key,newVal,receiver)
}
})
}
在vue 组件中,模板能不用 value 取到值,那是因为 setup 函数返回的数据会传递给 proxyRefs 函数进行处理。
reactive 也有自动调用 proxyRefs ,例子
const count = ref(1);
const obj = reactive(count);
obj.count // 1
最新文章
- jquery 清除动画队列不疑惑
- python基础——面向对象编程
- 专题——web.xml 中 url-pattern
- BZOJ-1008 越狱 数论快速幂
- debian linux 下安装 netbeans(php)
- java中的单例设计模式
- 【LeetCode OJ】Linked List Cycle
- Creader VIII VS. Creader VII+
- SWT的文件选择对话框I的使用
- 实用的android颜色配置表(亮瞎尼的双眼)
- [bzoj1594] [Usaco2008 Jan]猜数游戏
- 结合apache安装subversion
- JS中的 map, filter, some, every, forEach, for...in, for...of 用法总结
- 布局 android
- php配置-解决大数据超多字段的POST方式提交无法完全接受的问题
- lib下的Jar包在项目打包的时候提示不能找不到
- hibernate 的API使用
- 想做AI测试,需要学习哪些数学知识?
- linux编程之信号量
- ionic创建工程中遇到异常、错误及解决方法