一篇文章搞定Vue3响应式数据最常用的ref、reactive、computed、watch方法

发布时间:2023年12月21日

前言?

Vue3 中可以通过响应式 API 来创建响应式对象,相较于 Vue2 中使用 Object.definProperty 来劫持 get 和 set 不同,Vue3 中使用的是 Proxy 来创建响应式对象,使用Proxy有以下几点优势:

1. 对象新增属性不再需要手动 $set 添加响应式,Proxy 默认会监听动态添加属性和属性的删除等操作。

2. 消除无法监听数组索引,length 属性等等,不再需要在数组原型对象上重写数组的方法。

3. Object.defineproperty 是劫持所有对象属性的 get/set 方法,需要遍历递归去实现,Proxy 是代理整个对象。

4. Vue2 只能拦截对象属性的 get 和 set 操作,而 Proxy 拥有 13 种拦截方法。

下面介绍了Vue3中最常用搞定几个响应式函数ref、reactive、computed、watch

1. ref响应式数据

ref,接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value

ref中可以是基本数据类型也可以是引用数据类型

// 基本类型
let username = ref('xujingliang');
// 引用类型
let submitForm = ref({'username':'xujingliang','password':'123456'})

// 访问值
console.log(username.value);
console.log(submitForm.value.username);

// 修改值
username.value = "liudehua";
submitForm.value.username = "liudehua";

* 在template模版中使用ref响应式数据直接写名字即可

* 但是在js中如果想引用或者修改ref的值则需要加上.value属性来访问和修改值

2. reactive响应式函数

reactive ,返回一个对象的响应式代理。

reactive中的值只能是引用类型,即对象、数组

let userInfo = reactive({'username':'xujingliang','password':'123456'});

let userList =?reactive([

????????{'username':'xujingliang','password':'123456'},

????????{'username':'xujingliang','password':'123456'}

]);

// 访问userInfo中的值
console.log(userInfo.username);

// 修改userInfo中的值
userInfo.username = 'liudehua';

* 在template模版中使用reactive响应式数据直接写名字即可

* 与ref不同,在js中访问和修改reactive的值只需要访问变量名即可

总结:ref和reactive学完了,二者都是实现响应式数据,那么什么时候用ref?什么时候用reactive你知道吗?

?下面我就总结了常见的几种情况

变量类型使用方式
对象当变量为Object时适合使用reactive来定义
数组????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

1、如果数组内容赋值后不变动,很适合用reactive,比如从接口请求到的下拉选项,字典;
2、如果数组内容会根据某些情况变动,就适合用ref,比如分页表格。用reactive也可以,但是会想要修改渲染后的数据稍显麻烦;

数字、字符、布尔值

reactive不支持基本数据类型,只能用ref了

3. computed计算函数

computed,计算属性computed是依赖于使用它的数据,当数据发生变化时,自定义方法重新调用执行一次计算属性,监测的是依赖值,依赖变化的情况下才会重新计算。

<script setup>
import { ref,computed } from 'vue'

// 数量
const count = ref(10);

// 单价
const price = ref(9.99);

// 根据响应式数据count和price计算后的总价
const sum = computed(()=>{
  return count.value*price.value;  //基于响应式数据做计算之后的值
})

</script>

<template>
  <p>
    请输入数量:
    <input type="number" v-model="count" />
  </p>
  <p>
    请输入单价:
    <input type="number" v-model="price" />
  </p>

  <p>数量:{{count}},单价:{{price}},总共{{sum}}</p>
</template>

在实例代码中我们定义了响应式变量 商品数量:count 和 响应式变量 商品单价price,通过计算数量和单价之后,获取响应式数据商品总价的值sum;

4. watch侦听函数

watch,当需要在数据变化时执行异步或开销较大的操作时,computed是无法操作异步数据的,所以需要使用watch进行侦听。

4.1?watch侦听单个数据

侦听器watch作用是侦听一个或多个数据的变化,数据变化时执行的回调函数,两个额外参数:immediate(立即执行)和deep(深度侦听)?

<script setup>
import { ref,watch } from 'vue'

// 存放响应式数据count
const  count = ref(10);

// 存放状态的响应式数据 state
const state = ref("");

// 监听count数据的变化
watch(count,(newValue,oldValue)=>{
  state.value = "count发生了变化,当前值为"+count.value;
},{deep:true})


</script>

<template>
  <p>
    <button @click="count++">点击+1</button>
  </p>
  <p>
    状态:{{state}}
  </p>
</template>

示例代码中,我们通过点击按钮使响应式数据count自增,通过watch监听count的值变化进行操作。

?4.2?侦听多个数据
<script setup>
import { ref,watch } from 'vue'

// 存放响应式数据count
const  count = ref(10);

// 存放响应式数据price
const price= ref(9.9);

// 存放状态的响应式数据 state
const state = ref("");

// 监听count数据的变化
watch([count,price],([newCont,oldCount],[newPrice,oldPrice])=>{
  state.value = "count发生了变化,当前count值为:"+count.value+",当前price值为:"+price.value;
},{deep:true})

</script>

<template>
  <p>
    <button @click="count++">点击cont+1</button>
    &nbsp;
    <button @click="price++">点击price+1</button>
  </p>
  <p>
    状态:{{state}}
  </p>
</template>

示例代码中,我们通过点击按钮分别使响应式数据count和price自增,通过watch监听count和price的值变化进行操作。

4.3 精准的监听对象的某个值
<script setup>
import { ref,watch } from 'vue'

// 存放响应式数据userInfo
const  userInfo = ref({
  username:"admin",
  password:"123456"
});

// 触发password修改
setTimeout(()=>{
  userInfo.value.password = "123123";
},3000)

// 监听userInfo中的值变化
watch(
  ()=>userInfo.value.password,
  (newValue,oldValue)=>{
    alert("密码发生改变")
  },
  {
    immediate:true,
    deep:true
  }
)

</script>

<template>

</template>

在上述代码示例中,我添加了两个参数,一个是immediate,一个是deep

immediate:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调,其语法格式如下。

?deep:通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行。

文章来源:https://blog.csdn.net/qq_41765777/article/details/135060280
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。