您的位置:首页 >聚焦 >

当前观察:【Vuejs】1402- 6 个你必须明白 Vue3 的 ref 和 reactive 问题(入门篇)

2022-08-08 18:43:18    来源:程序员客栈

Vue3 为开发者提供 ref和 reactive两个 API 来实现响应式数据,这也是我们使用 Vue3 开发项目中经常用到的两个 API。

本文从入门角度和大家介绍这两个 API,如果有错误,欢迎一起讨论学习~

「本文演示代码是基于 Vue3 setup 语法。」


【资料图】

在入门阶段,我们需要掌握的是「是什么」、「怎么用」、「有什么注意」,基本就差不多了。

1. reactive API 如何使用?

reactive方法用来创建响应式对象,它接收一个对象/数组参数,返回对象的响应式副本,当该对象的属性值发生变化,会自动更新使用该对象的地方。

下面以分别以「对象」和「数组」作为参数演示:

import{reactive}from"vue"letreactiveObj=reactive({name:"Chris1993"});letsetReactiveObj=()=>{reactiveObj.name="HelloChris1993";}letreactiveArr=reactive(["a","b","c","d"]);letsetReactiveArr=()=>{reactiveArr[1]="HelloChris1993";}

模版内容如下:

此时页面展示如下:

当我们分别点击 Update按钮后,可以看到数据变化后,视图上内容也一起更新了:

2. ref API 如何使用?

ref的作用就是将一个「原始数据类型」(primitive data type)转换成一个带有「响应式特性」的数据类型,原始数据类型共有7个,分别是:String/ Number/BigInt/Boolean/Symbol/Null/Undefined。

ref的值在 JS/TS 中读取和修改时,需要使用 .value获取,在模版中读取是,不需要使用 .value。

下面以分别以「字符串」和「对象」作为参数演示:

import{ref}from"vue"letrefValue=ref("Chris1993");letsetRefValue=()=>{refValue.value="HelloChris1993";}letrefObj=ref({name:"Chris1993"});letsetRefObj=()=>{refObj.value.name="HelloChris1993";}

模版内容如下:

此时页面展示如下:

当我们分别点击 Update按钮后,可以看到数据变化后,视图内容也一起更新了:

3. reactive 可以用在深层对象或数组吗?

答案是「可以的」,reactive是基于 ES2015 Proxy API 实现的,它的响应式是整个对象的所有嵌套层级。

下面以分别以「对象」和「数组」作为参数演示:

import{reactive}from"vue"letreactiveDeepObj=reactive({user:{name:"Chris1993"}});letsetReactiveDeepObj=()=>{reactiveDeepObj.user.name="HelloChris1993";}letreactiveDeepArr=reactive(["a",["a1","a2","a3"],"c","d"]);letsetReactiveDeepArr=()=>{reactiveDeepArr[1][1]="HelloChris1993";}

模版内容如下:

此时页面展示如下:

当我们分别点击 Update按钮后,可以看到数据变化后,视图上内容也一起更新了:

4. reactive 返回值和源对象相等吗?

答案是「不相等的」,因为reactive是基于 ES2015 Proxy API 实现的,返回结果是个 proxy 对象。

测试代码:

letreactiveSource={name:"Chris1993"};letreactiveData=reactive(reactiveSource);console.log(reactiveSource===reactiveData);//falseconsole.log(reactiveSource);//{name:"Chris1993"}console.log(reactiveData);//Reactive<{name:"Chris1993"}>

5. TypeScript 如何写 ref 和 reactive 参数类型?

在使用 TypeScript 写 ref / reactive 参数类型时,可以根据 ref / reactive 接口类型来实现具体的类型:

functionref(value:T):Reffunctionreactive(target:T):UnwrapNestedRefs

将前面实例代码改造一下:

import{ref}from"vue"letrefValue=ref("Chris1993");// refValue 类型为:RefletsetRefValue=()=>{refValue.value="HelloChris1993";//ok!refValue.value=1993;//error!}//reactive也类似letreactiveValue=reactive<{name:string}>({name:"Chris1993"});

6. 把 ref 值作为 reactive 参数会怎么样?

当我们已有一个 ref对象,需要使用在 reactive对象中,会发生什么呢?

假设:

letname=ref("Chris1993");letnameReactive=reactive({name})

我们可以做下列操作:

letname=ref("Chris1993");letnameReactive=reactive({name})console.log(name.value===nameReactive.name);//truename.value="HelloChris1993";console.log(name.value);//HelloChris1993console.log(nameReactive.name);//HelloChris1993nameReactive.name="HiChris1993";console.log(name.value);//HiChris1993console.log(nameReactive.name);//HiChris1993

这是因为 reactive将会对所有深层的 refs进行解包,并且保持 ref的响应式。

当通过赋值方式将 ref分配给 reactive属性时,ref也会自动被解包:

letname=ref("Chris1993");letnameReactive=reactive({})nameReactive.name=name;console.log(name.value);//Chris1993console.log(nameReactive.name);//Chris1993console.log(name.value===nameReactive.name);//true

7. 总结

本文主要从入门角度和大家介绍reactive/ ref两个 API 的使用方式区别,还有使用过程中的几个问题。

简单总结一下:

reactive一般用于对象/数组类型的数据,都不需要使用 .value;ref一般用于基础数据类型的数据,在 JS 中读取和修改时,需要使用 .value,在模版中使用时则不需要;reactive可以修改深层属性值,并保持响应;reactive返回值和源对象不同;reactive的属性值可以是 ref值;

下一篇将和大家分享精通篇,欢迎大家期待。

关键词: 大家介绍 不需要使用 原始数据

相关阅读