vue3 watch 的多种场景用法(ref,reactive,getter函数,数组)

vue3 watch 的多种场景用法(ref,reactive,getter函数,数组)

在这里插入图片描述
上面是vue3官方文档给出的说明,看不懂没关系,接下来我将会针对实际中各种场景给出说明,当你全部看完后再回来看这个说明,就会一目了然。

监听单个数据

  1. ref基本数据类型
  2. ref响应式对象的单个数据
  3. reactive响应式对象的单个数据

ref基本数据类型

	import { watch,ref} from 'vue' // 导入watch和ref
    // 响应式变量
    const sum = ref(1)
    // 绑定函数
    function changeSum(){
    	sum.value += 1
    }
    // 对sum进行监听
    watch(sum, (newValue,oldValue) => {
      console.log('sum改变了')
    }, { immediate: true })

watch是一个函数,接收的参数有三个:

  1. 监听的数据sum,在ref定义的基本数据类型中,不需要加value
  2. 回调函数(newValue,oldValue) => { console.log('sum改变了') },回调函数接收两个参数,newValue新值,oldValue旧值
  3. 配置对象{ immediate: true }),表示立即监听,即从声明 const sum = ref(1)时就会触发回调函数,此时newValue为1,oldValue为undefined

ref响应式对象的单个数据

import { watch, ref } from 'vue';
// 响应式变量
const person = ref({
 name: '马嘉祺',
 age: 18 
});
// 监听 person.name 的变化
watch(
 () => person.value.name, // 返回需要监听的响应式引用
 (newValue, oldValue) => {
   console.log(`name 从 ${oldValue} 变为了 ${newValue}`);
 }
);
// 模拟 name 属性变化
function changeName(newName) {
 person.value.name = newName;
}

对于监听ref响应式对象的单个属性,watch函数并不支持直接监听person.value.name,引起其本身不是ref定义的(ref定义的是person),所以我们需要写成一个getter函数的返回形式 () => person.value.name

reactive响应式对象的单个数据

import { reactive, watch } from 'vue';
// 创建一个响应式对象
const person = reactive({
  name: '马嘉祺',
  age: 18
});
// 监听 person 对象中的 name 属性
watch(
  () => person.name, // 返回需要监听的响应式属性
  (newValue, oldValue) => {
    console.log(`name 从 ${oldValue} 变为了 ${newValue}`);
  }
);
// 模拟 name 属性变化
function changeName(newName) {
  person.name = newName;
}

在监听对象的单个属性时,ref和reactive的用法没有太大区别,可能也就是.value的区别

监听整个对象

  1. ref监听
import { ref, watch } from 'vue';
// 使用 ref 定义一个响应式对象
const person = ref({
  name: '马嘉祺',
  age: 18,
  address: {
    city: '北京',
    country: '中国'
  }
});
// 监听整个 person 对象的变化,也可以写成函数返回形式 () => person.value
watch(person, (newValue, oldValue) => {
  console.log('person 对象发生了变化:', newValue);
  // 注意:这里 newValue 和 oldValue 都是对象的引用
}, { deep: true }); // 深度监听,确保内部属性变化也能触发回调

// 模拟 person 对象的 name 属性变化
function changeName(newName) {
  person.value.name = newName;
}
// 模拟 person 对象的 address 属性变化
function changeAddress(newCity, newCountry) {
  person.value.address.city = newCity;
  person.value.address.country = newCountry;
}
  1. 对于ref定义的响应式对象,既可以写person(本身就是ref定义的)也可以写成函数返回形式() => person.value
  2. 回调函数仍然是接收两个参数newValue新值,oldValue旧值,不过这里的值都将是整个person对象,而不是其中的某一个改变的值
  3. 配置对象中,{ deep: true }表示开启深层监听,即监听对象里面每一个键值对的改变,如果不加,则watch只会监听person整个对象的变化(对象是引用类型,实际person指向的是地址,只有改变地址把整个对象换掉,才会触发watch)
  1. reactive监听
import { reactive, watch } from 'vue';
// 创建一个响应式对象
const person = reactive({
  name: '马嘉祺',
  age: 18,
  address: {
    city: '北京',
    country: '中国'
  }
});
// 监听整个 person 对象的变化
watch(
   person, // 也可以直接用函数返回形式() => person
  (newValue, oldValue) => {
    console.log('person 对象发生了变化:', newValue);
  },
  // { deep: true } reactive默认开启深层监听,不需要自己写
);

// 模拟 person 对象的 name 属性变化
function changeName(newName) {
  person.name = newName;
}
// 模拟 person 对象的 address 属性变化
function changeAddress(newCity, newCountry) {
  person.address.city = newCity;
  person.address.country = newCountry;
}
  1. 对于ref定义的响应式对象,既可以写person(本身就是reactive定义的)也可以写成函数返回形式() => person
  2. 回调函数仍然是接收两个参数newValue新值,oldValue旧值,不过这里的值都将是整个person对象,而不是其中的某一个改变的值
  3. 配置对象中,{ deep: true }表示开启深层监听,但是在reactive定义的响应式对象中,是默认开启的

监听对象中的部分数据

前面已经讲过了ref定义,reactive定义,函数返回形式,在vue3的官方文档中还给出了数组形式的监听,就是用于监听对象中部分数据
场景:用户信息中有几十个属性,而实际只需要监听用户的余额和年龄,监听单个实现不了,监听全部频繁触发影响性能

  1. 可以写多个watch函数监听单个数据
  2. 用数组的形式写一次即可
import { watch,reactive } from 'vue';
const person = reactive({
  name: '马嘉祺',
  age: 18,
  address: {
    city: '北京',
    country: '中国'
  }
});
// 使用 watch 函数监听 person.name 和 person.address.city
watch(
  // 传入一个数组,包含要监听的响应式源,单个数据推荐采用函数返回形式
  [() => person.name, () => person.address.city],
  // 回调函数接收两个参数:新值数组[newName, newCity]和旧值数组[oldName, oldCity]
  ([newName, newCity], [oldName, oldCity]) => {
    console.log(`Name changed from ${oldName} to ${newName}`);
    console.log(`City changed from ${oldCity} to ${newCity}`);
  }
);
  1. 监听对象要写成数组形式[() => person.name, () => person.address.city]每个元素都是一个函数返回形式
  2. 回调函数中仍然是两个参数,前者是新值后者是旧值,但是类型都变成了数组,不要误认为是([newName, newCity], [oldName, oldCity]),新的全在前面,旧的全在后面

停止监听

import { reactive, watch } from 'vue';

const person = reactive({
  name: '马嘉祺',
  age: 18,
  address: {
    city: '北京',
    country: '中国'
  }
});

// 设置一个监听器,并立即检查是否需要停止监听
const stopWatch = watch(
  [() => person.name, () => person.address.city],
  ([newName, newCity], [oldName, oldCity]) => {
    console.log(`Name changed from ${oldName} to ${newName}`);
    console.log(`City changed from ${oldCity} to ${newCity}`);
   if (newName == '') {
    console.log('停止监听');
    stopWatch (); // 停止监听
  },
  { immediate: true } // 立即执行回调函数
);

watch是一个函数,他的返回值也是一个函数,也就是用来停止监听的函数,我们用stopWatch变量进行接收,然后在变化的时候(也可以写在watchEffect里面,但是这篇文章只介绍watch)调用stopWatch()即可停止监听

总结:在实践中的用法

  1. watch的第一个参数响应式属性,不管是单个基本数据,还是整个对象,统一写成函数返回形式 () => person.age 或 () => person,person无论是ref或者reactive定义的都可以适用,当要同时监听多个数据的时候,也是采用数组包函数返回形式。
  2. 回调函数的两个参数,前者永远是新值,后者永远是旧值,根据监听的数据是单个还是多个决定参数是值 (newName,oldName) => {具体逻辑}还是数组 ([newName, newCity], [oldName, oldCity]) => {具体逻辑}
  3. 配置对象,主要有两个{deep:true}用于开启深层监听(主要用于ref定义的响应式对象,可以监听到对象的每一个属性;{immediate:true}用于开启立即监听,在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。
  4. 可以用一个变量接收监听器watch函数(返回值是一个停止函数),在某下情况下调用变量停止监听
  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3中,您可以使用`ref`和`reactive`来声明变量和对象。对于数组类型的变量和对象,您可以使用JavaScript提供的`Array`和`Object`方法来修改它们的值。 对于`ref`声明的数组类型,您可以使用`value`属性来获取或修改它的值。例如: ```vue <template> <div> <h1>{{ myArray }}</h1> <button @click="updateArray">Update Array</button> </div> </template> <script> import { ref } from 'vue'; export default { setup() { const myArray = ref([1, 2, 3]); const updateArray = () => { myArray.value.push(4); }; return { myArray, updateArray }; } }; </script> ``` 在这个例子中,我们使用`ref`声明了一个数组类型的变量`myArray`,并初始化它为`[1, 2, 3]`。我们还定义了一个`updateArray()`函数,用于将数字4添加到`myArray`中。在`updateArray()`函数中,我们使用`myArray.value`来访问`myArray`的值,并使用`push()`方法将数字4添加到数组末尾。 对于`reactive`声明的数组类型,您可以使用`Array`方法来修改它的值。例如: ```vue <template> <div> <h1>{{ myArray }}</h1> <button @click="updateArray">Update Array</button> </div> </template> <script> import { reactive } from 'vue'; export default { setup() { const myArray = reactive({ numbers: [1, 2, 3] }); const updateArray = () => { myArray.numbers.push(4); }; return { myArray, updateArray }; } }; </script> ``` 在这个例子中,我们使用`reactive`声明了一个对象`myArray`,其中包括一个数组属性`numbers`,初始化为`[1, 2, 3]`。我们还定义了一个`updateArray()`函数,用于将数字4添加到`numbers`数组中。在`updateArray()`函数中,我们使用`myArray.numbers`来访问`numbers`数组,并使用`push()`方法将数字4添加到数组末尾。 总之,无论是`ref`还是`reactive`声明的数组类型,您都可以使用JavaScript提供的`Array`方法来修改它们的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值