文章目录
- 三、其它 Composition API(不常用,了解即可)
- 3.toRaw 与 markRaw
- 测试案例
- 完整代码
- 本人其他相关文章链接
三、其它 Composition API(不常用,了解即可)
3.toRaw 与 markRaw
注意点1:
之前上面讲解的函数都是把普通数据 -> 响应式数据,如图红线1,但是有时我们也需要把响应式数据 -> 普通数据,如图绿线2
注意点2:
问题:如图,我先用toRaw(person)把响应式person对象转为p普通对象,然后一顿修改p的age属性,那么页面会更新值吗?
答案:不会,因为p的对象类型为Object,它不是一个响应式的,所以修改无效。
结果展示如图:
注意点3:
toRaw函数只处理reactive缔造的响应式数据有效,针对ref缔造的响应式数据无效,比如代码如图1,点击按钮“输出最原始的person”,打印ref缔造的响应式数据结果如图2,打印reactive缔造的响应式数据结果如图3。
如图1
如图2
如图3
注意点4:
问题:假设我给person新增个car属性,代码如下,但是报错了为啥?,报错如图1
如图1
答案:你执行到…toRefs(person)的时候,addCar按钮和方法还没执行呢,也就是初始化时person里面还没有car属性呢,你项目启动后模板渲染后肯定报错啊,报错说car没定义在实例上。但是哪怕…toRefs(person)执行后你再往person对象新增个car属性,…toRefs(person)也不会再执行一遍,因为如果…toRefs(person)想再执行一遍,除非setup()再执行一遍,但很可惜整个项目启动后setup()只会执行一遍。
解决方案是:有2种解决办法:
- 办法1:在定义person对象时,先定义一个空的car属性用来占位
- 办法2:在return返回对象中,在…toRefs(person)的上面提前返回个person对象,同时修改<h3>标签体内容即可。
原理是:在…toRefs(person)的上面提前返回个person对象,就会把整个person响应式对象交出去,这个person响应式对象中任何属性发生变化都能被vue监测到。
注意点5:
问题:针对注意点4中代码,为啥定义person.car = car,也行实现person中car属性的的响应式?car不是定义普通的Object类型的对象吗?
答案:因为return配置了返回person,就相当于配置了Proxy代理,只要捕获到对person任何属性的操作,任何属性的操作都是响应式的。
注意点6:
person.car = markRaw(car),使用markRaw函数,可以使person中car属性无法进行修改,案例效果如图:toRaw与markRwa-注意点6-结果展示.gif,需要说明的是:car内部属性值已经改了,只是没有响应式更新而已,它和readonly不同,readonly是压根不让修改。
toRaw与markRwa-注意点6-结果展示.gif
注意点7:
问题:何时使用markRaw?
答案:
- 场景1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
- 场景2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
注意点8:
问题:针对注意点7中场景1,如何理解使用复杂的第三方类库时最好使用markRaw函数标记?
答案:如图,假设person中axios这个是第三方类库提供的超级复杂至少二三十层嵌套的数据,当你return配置返回person对象时,那么第三方类库提供的超级复杂的axios数据中,所有的属性都会做proxy代理做响应式,明显会超级浪费资源且效率太低,所以需要用markRaw进行标记为只读不可修改,这样vue监测到就不会把axios数据中所有的属性都会做proxy代理做响应式,从而达到节省了资源消耗的目的,且解决效率太低的问题。
测试案例
完整代码
项目目录
main.js
App.vue
Demo.vue
结果展示:
本人其他相关文章链接
1.《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等 2.vue3知识点:shallowReactive 与 shallowRef
3.vue3知识点:readonly 与 shallowReadonly
4.vue3知识点:toRaw 与 markRaw
5.vue3知识点:customRef
6.vue3知识点:provide 与 inject
7.vue3知识点:响应式数据的判断