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

最新文章

  1. jquery 清除动画队列不疑惑
  2. python基础——面向对象编程
  3. 专题——web.xml 中 url-pattern
  4. BZOJ-1008 越狱 数论快速幂
  5. debian linux 下安装 netbeans(php)
  6. java中的单例设计模式
  7. 【LeetCode OJ】Linked List Cycle
  8. Creader VIII VS. Creader VII+
  9. SWT的文件选择对话框I的使用
  10. 实用的android颜色配置表(亮瞎尼的双眼)
  11. [bzoj1594] [Usaco2008 Jan]猜数游戏
  12. 结合apache安装subversion
  13. JS中的 map, filter, some, every, forEach, for...in, for...of 用法总结
  14. 布局 android
  15. php配置-解决大数据超多字段的POST方式提交无法完全接受的问题
  16. lib下的Jar包在项目打包的时候提示不能找不到
  17. hibernate 的API使用
  18. 想做AI测试,需要学习哪些数学知识?
  19. linux编程之信号量
  20. ionic创建工程中遇到异常、错误及解决方法

热门文章

  1. 一条命令查看docker容器的ip地址
  2. PostgreSQL 选择数据库
  3. 各编程语言 + aardio 相互调用示例
  4. Codeforces Round #823 (Div. 2) A-D
  5. 关于Azure-AzCopy在Linux环境下的安装
  6. Linux命令系列之ls——原来最简单的ls这么复杂
  7. Redis高可用之主从复制原理演进分析
  8. MySQL之安装(linux两种版本版本安装)
  9. Vue中引入echarts。
  10. 七、kubernetes污点和容忍