回首Vue3之API篇(八)

700 阅读4分钟

这是我参与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.countcount.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仍不是响应式的。

总结

  1. 这些api中,我们常用的应该是reactivereadonlymarkRaw这三个了,值得我们注意的是:有时候我们的数据不需要时响应式的,这时候我们可以用markRaw标记数据。

  2. 我们在处理数据,或者对数据进行判断的时候会用到这些api,我们要根据实际情况来使用它们。

想了解更多文章,传送门已开启:回首Vue3目录篇