这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战
这篇文章我们来讲一下响应性基础 API的使用,以及我们需要注意的地方。
如何使用
reactive
reactive 让我们得到一个对象的响应式副本,响应式转换是“深层”的——它影响所有嵌套 property。在基于 ES2015 Proxy 的实现中,返回的 proxy 是不等于原始对象的。使用如下:
setup: () => {
const obj = reactive({ count: 0 })
return { obj }
}
这样我们就可以像Vue2一样使用obj.count,当然它还有另一个作用:包所有深层的 refs,同时维持 ref 的响应性。
示例
const count = ref(1)
const obj = reactive({ count })
上述示例,不但ref会被解包,也就是说obj.count===count.value,而且当obj.count或count.value发生变化的时候,另一个也会改变。
值得我们注意的是:当将 ref 分配给 reactive property 时,ref 也将被自动解包,如下:
const count = ref(1)
const obj = reactive({})
obj.count = count
此处的运行结果和上述示例的结果是一样的情况。
readonly
接受一个对象 (响应式或纯对象) 或 ref 并返回原始对象的只读代理,任何被访问的嵌套 property 也是只读的,如下:
const obj = reactive({ count: 0 })
const copyObj=readonly(obj)
当我们让obj.count++变化时,copyObj.count的值也会随之变化,但是当我们让copyObj.count++变化时,出现如下警告:
Set operation on key "count" failed: target is readonly.
也就是说我们可以用readonly复制一份只读不能写的数据,这样我们项目中是很实用的,比如我们在某个地方只使用某个数据,但是不能更改它,此时我们用它就很方便。
isProxy
检查对象是否是由 reactive 或 readonly 创建的 proxy,使用如下:
isProxy(obj) //true
isProxy(copyObj) //true
const title=ref('hello world')
isProxy(title) //false
isReactive
检查对象是否是由 reactive 创建的响应式代理,另外用readonly 创建的只读 proxy,检查的时候也会返回true,使用如下:
isReactive(obj) //true
isReactive(copyObj) //true
isReactive(title) //false
isReadonly
有了上述两个is[xxx]方法的使用,我们可以看出此方法是检查对象是否是由 readonly 创建的只读代理,使用如下:
isReadonly(obj) //false
isReadonly(copyObj) //true
toRaw
返回 reactive 或 readonly 代理的原始对象。就是脱Proxy化,获取最原始的数据值,使用如下:
toRaw(obj)
//{count: 0}
从代码中可以看出数据去掉了Proxy,只剩原始的数据:{count: 0}。
markRaw
标记一个对象,使其永远不会转换为 proxy,永远都是本身,假定我们标记一个对象,如下:
const foo = markRaw({})
那么他在被reactive 或 readonly方法调用的时候都不会改变,也就是说你在使用isProxy、isReactive、isReadonly这三个方法的时候,得到的结果都是false。
不知你是否有注意,在项目中,有时我们不需要响应性数据,只是调用的使用,那我们就可以用markRaw来标记数据。
shallowReactive
创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换,也就是说只是浅层的响应式。它也与 reactive 不同,任何使用 ref 的 property 都不会被代理自动解包。
假定我们定义一个变量如下:
setup() {
const title = ref('hello world')
const obj = shallowReactive({
count: 0,
a: {
b: 1
},
title: title
})
return {
obj
}
}
上述代码中,obj.count还是响应式的,但obj.a.b不是了,如果发生了变化,视图也不会发生变化。还有一点是obj.title不会被自动解包,我们要这样使用:
<h1>{{obj.title.value}}</h1>
否则是解析不出来的。
shallowReadonly
创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换。类比shallowReactive,它也与 readonly 不同,任何使用 ref 的 property 都不会被代理自动解包,使用方法也一样,但是不一样的是:
我们改变obj.count++时会报出警告,但是改变obj.a.b++不会报错,是有作用的,虽然obj.a.b仍不是响应式的。
总结
-
这些api中,我们常用的应该是
reactive、readonly、markRaw这三个了,值得我们注意的是:有时候我们的数据不需要时响应式的,这时候我们可以用markRaw标记数据。 -
我们在处理数据,或者对数据进行判断的时候会用到这些api,我们要根据实际情况来使用它们。
想了解更多文章,传送门已开启:回首Vue3目录篇 !