前言
在做项目的时候使用reactive时遇到了一些问题,自己挖的坑,花多大力气也要将他填平,因此想写一篇文章,细致的分析一下reactive
错误一:直接赋值
let MenuList: any = reactive([]) const res= await getMenuList()//请求接口 MenuList=res
我们可以先了解一下reactive是如何解决响应式的,我们知道在Vue3中reactive是使用了ES6中的新增语法proxy代理来实现响应式
Proxy是一个构造函数,是实现对一整个对象的监听而不是像defineProperty的对属性名监听,在创建时传入两个参数,第一个是需要被代理的对象,第二个是代理的配置对象(至少要传一个空对象,否则会报错),而这个对象中可以除了get/set还有一个deleteProperty,会在代理对象中的属性值被删除时调用,同时代理对象中被追加一个属性的时候也会调用set
这个方式解决vue2中(追加属性/删除属性)无法监听到的问题
但是如果我们直接对reactive所创造的响应式对象重新赋值就会破坏原有的响应式对象的引用地址,因此就会失去响应式,所以我们是不可以直接赋值的
错误二:解构赋值
//定义一个数据 let data=reactive({ username:"jack", age:32 }) let {username}=data
这种方式同样会失去响应式,这是为什么呢?
首先我们要大概理解一下reactive的底层实现是通过proxy来实现的响应式,首先通过proxy来进行拦截,然后,当数据发生变化的时候就通知Vue进行视图的更新。
function reactive (obj) { return new Proxy(obj, { get (target, key) { return Reflect.get(target, key) }, set (target, key, value) { return Reflect.set(target, key, value) } }) }
解构其实和直接赋值是一个道理,都是直接跳过了代理这个过程,直接将变量进行了赋值,这样就会使获得的数据失去响应式
错误的解决😄😄
方式一:可以先定义一个对象,然后在内部定义数组/对象
let MenuList =reactive({ useList:[] }) const res= await getMenuList()//请求接口 MenuList.useList=res
通过这种方式没有直接将MenuList的地址更改,因此不会失去响应式。
方式二:通过使用Object.assign来进行对象的合并
let MenuList =reactive([]) const res=await getMenuList() Object.assign(MenuList,res)
通过使用Object.assign将获取到的值与MenuList合并,没有修改MenuList地址,这样做也不会丢失响应式。
Object.assign方法✌️✌️
这里简单的介绍一下
Object.assign(target, ...sources)
参数: target--->目标对象 source--->源对象
返回值:target,即目标对象
效果就是可以实现将sources中的属性方法合并到target上面
ref和reactive的区别
首先来说reactive
- 所接收的值必须时对象或者是数组
- 底层通过将传入的数据包裹成proxy来实现响应式
- reactive是通过ES6中的Proxy实现数据劫持,并通过Reflect去操作源对象内部的数据
ref :
- 可以接收基本数据类型,当然也可以接收对象数组等数据类型
- 当接收的值是对象时,底层还是通过proxy来实现
- ref通过Object.defineProperty中的get和set去实现时响应式(数据劫持)
总结
这个是在开发过程中遇到的小错误,所以我们要注意学习时的对细节知识的加深学习,遇到错误及时解决