在Vue3中,watch
特性进行了一些改变和优化。与computed
不同,watch
通常用于监听数据的变化,并执行一些副作用,例如发送网络请求、更新DOM等。本文将介绍Vue3中watch
特性。
watch(source, callback, options?)
其中,source
表示要监听的数据,可以是一个响应式的数据对象、一个计算属性或一个方法的返回值;callback
表示当数据发生变化时要执行的回调函数;options
表示watch的一些配置选项,例如immediate
、deep
、flush
等。
ref
的值,直接监听<template>
<div>
case1:<input v-model="userName" type="text">
div>
template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const userName= ref<string>('张三');
watch(userName, (newVal, oldVal) => {
console.log(newVal, oldVal);
})
script>
ref
的值,采用数组形式<template>
<div>
case1:<input v-model="userName" type="text">
case2:<input v-model="age" type="text">
div>
template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const userName= ref<string>('张三');
const age= ref<number>(18);
watch([userName, age], (newVal, oldVal) => {
console.log(newVal, oldVal);
})
script>
ref
实现深层次对象的响应式,侦听的时候需要开启深度侦听reactive
实现响应式,开启deep
和不开启deep
效果是一样的<template>
<div>
case1:<input v-model="obj.foo.bar.name" type="text">
div>
template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
const obj = reactive({
foo: {
bar: {
name: '张三'
}
}
})
watch(obj, (newVal, oldVal) => {
console.log(newVal, oldVal);
}, {
// deep: true, // 深度侦听, 监听ref创建的响应式对象必须开启
})
script>
注意:此处监听的新值和旧值相同
,主要是因为新旧值引用地址是相同的,此处可采取computed
计算属性先实现深拷贝。示例如下:
import { reactive, watch, computed } from 'vue';
const obj = reactive({
foo: {
bar: {
name: '张三'
}
}
})
let obj1 = reactive({})
obj1 = computed(() => {
return JSON.parse(JSON.stringify(obj))
})
watch(obj1, (newVal, oldVal) => {
console.log(newVal, oldVal);
})
reactive
响应式对象单一属性,采用回调函数
的形式<template>
<div>
case1:<input v-model="obj.foo.bar.name" type="text">
div>
template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
const obj = reactive({
foo: {
bar: {
name: '张三'
}
}
})
watch(
() => obj.foo.bar.name,
(newVal, oldVal) => {
console.log(newVal, oldVal);
}
)
script>
在Vue3中,watch特性进行了一些改变和优化。除了基本的watch用法外,还有一些高级用法可以使watch更加灵活和方便。下面是几个常用的高级用法:
immediate
选项可以用于指定watch
在组件创建时立即执行一次回调函数,而不必等待数据的变化。例如:
import { reactive, watch } from 'vue'
const state = reactive({
count: 0
})
watch(
() => state.count,
(newVal, oldVal) => {
console.log(`count值从${oldVal}变成了${newVal}`)
},
{ immediate: true }
)
在上面的例子中,我们使用immediate
选项将watch的回调函数在组件创建时立即执行了一次,输出了初始值。当state.count
变化时,watch的回调函数还会被再次执行。
deep
选项可以用于深度监听
一个对象或数组的变化。当我们监听一个对象或数组时,默认情况下只会监听对象或数组的引用变化,而不会监听其内部数据的变化。如果我们需要深度监听
对象或数组内部数据的变化,可以使用deep
选项。例如:
import { reactive, watch } from 'vue'
const state = reactive({
todos: [
{ id: 1, text: '学习Vue3', done: false },
{ id: 2, text: '学习React', done: false },
{ id: 3, text: '学习Angular', done: true }
]
})
watch(
() => state.todos,
(newVal, oldVal) => {
console.log(`todos数组发生了变化`)
},
{ deep: true }
)
state.todos[0].done = true // 输出:todos数组发生了变化
注意:当我们使用deep
选项时,watch
的性能会受到一定的影响,因为Vue
需要对对象或数组进行递归遍历。因此,只有在必要的情况下才应该使用deep
选项。
flush
选项可以用于指定watch
的回调函数在何时执行。例如:
import { reactive, watch } from 'vue'
const state = reactive({
count: 0
})
watch(
() => state.count,
(newVal, oldVal) => {
console.log(`count值从${oldVal}变成了${newVal}`)
},
{ flush: 'sync' }
)
state.count++ // 输出:count值从0变成了1
在上面的例子中,我们使用flush选项将watch的回调函数在同步模式下执行了,这意味着watch的回调函数会在数据变化之后立即执行。当我们执行state.count++
时,会触发count
的变化,从而执行watch的回调函数并输出变化的值。
在使用watch时,为了优化性能,我们可以采取以下一些方法:
在有些情况下,如果我们只是想监听一个值的变化,并在变化时执行一些操作,我们可以使用computed
代替watch
。computed
可以自动缓存计算的结果,只有在它的依赖项变化时才会重新计算,因此可以提高一定的性能。例如:
import { reactive, computed } from 'vue'
const state = reactive({
count: 0
})
const doubleCount = computed(() => {
return state.count * 2
})
console.log(doubleCount.value) // 输出:0
state.count++
console.log(doubleCount.value) // 输出:2
在有些情况下,我们可能会频繁地监听
一个值的变化,并在变化时执行一些操作。如果回调函数执行的太频繁,会影响性能
。为了避免这种情况,我们可以使用throttle
和debounce
控制回调函数的执行频率。
throttle
和debounce
都是用于控制函数执行频率的工具函数。throttle
可以用于控制函数在一定时间内只能执行一次,而debounce
可以用于控制函数在一定时间内不会连续执行。例如:
import { reactive, watch } from 'vue'
import { throttle } from 'lodash-es'
const state = reactive({
count: 0
})
watch(
() => state.count,
throttle((newVal, oldVal) => {
console.log(`count值从${oldVal}变成了${newVal}`)
}, 1000)
)
state.count++
watch特性是Vue中非常重要的一个特性,通过学习watch的基础概念、高级用法、实战应用和性能优化方法,可以帮助我们更好地理解和应用Vue。