关于前端:vue3侦听器

2次阅读

共计 2709 个字符,预计需要花费 7 分钟才能阅读完成。

侦听器🎞️

侦听器和计算属性都能够用于侦听响应式数据的变动,如果须要在数据变动后 执行操作,批改依赖项 ,那么就应该应用 侦听器
watchwatchEffect都能够侦听数据源并执行回调操作,不同的是他们追踪响应式依赖的形式。

watch:只追踪指定的数据源,所以能够准确地管制回调函数的触发机会

watchEffect:主动追踪回调内的响应式数据,相比 watch 更加简洁,但有时其响应性依赖关系会不那么明确。

视频链接

watch 函数

第一个参数须要指定须要侦听的数据。
能够是 响应式数据 (ref、reactive、computed…)、getter 函数、也能够是以上数据源组成的 数组, 也就是同时侦听多个数据源。

第二个参数是在侦听到数据变动时,须要执行的回调办法。
该回调办法有两个参数,第一个为数据更新后的值,第二个为数据更新前的值。

import {ref, watch} from 'vue'

const count = ref(0)
const price = ref(10)

// 侦听响应式数据
watch(count, (newVal, oldVal) => {
    // 每当 count 更新时,都会执行这里的函数

    console.log("new count:", newVal) // 1  更新后的值
    console.log("old count:", oldVal) // 0  更新前的值
})

// 侦听 getter 函数
watch(() => count.value * price.value,
    (newVal, oldVal) => {
        // 每当 count 或者 price 更新时,都会执行这里的函数

        console.log("新总价:", newVal) // 10  更新后的值
        console.log("旧总价:", oldVal) // 0  更新前的值
    })

// 应用数组侦听多个数据源
watch([count, () => price.value],
    (newValArr, oldValArr) => {
        // 每当 count 或者 price 更新时,都会执行这里的函数

        // 须要留神此时的回调数据为数组
        // newValArr[0] count
        // newValArr[1] () => price.value]
        // oldValArr 同上
        console.log(newValArr) // [1, 10]  更新后的值
        console.log(oldValArr) // [0, 10]  更新前的值
    })

count.value++ // 更新 count 值

可选配置

以上两个参数在侦听器中是必传的, 除此之外 watch 函数还有一些可选配置。

立刻执行

watch 默认是在数据源更新时才会执行回调,如果想要在创立时立即执行回调函数,就能够通过传入 immediate:true 使侦听器的回调立刻执行

const count = ref(0)

watch(count, (newVal,oldVal) => {console.log(newVal)  // 0
    console.log(oldVal)  // undefind
}, {immediate: true  // 创立时立刻执行一次回调})

深层侦听器

给 watch 函数传入一个响应式对象,会隐式地创立一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发:

const obj1 = reactive({val: 1})

watch(obj1, (newVal, oldVal) => {
    // 在 obj 的嵌套属性变更时触发
    // 留神此处的 newVal oldVal 的值是相等的
    // 因为他们是同一个对象
})

const obj2 = ref({val: 2})

// 传入 ref 侦听的对象时,增加.value 才会默认创立深层侦听
watch(obj2.value, (newVal, oldVal) => {})

obj1.val++
obj2.value.val++

当间接传入 ref 创立的对象或是返回响应式对象的 getter 函数时, 只有在它们的对象被整个替换时才会触发回调。如果也想创立深层侦听, 能够通过传入 deep:true 强制转成深层侦听器。

// 当间接传入 ref 创立的对象或是返回响应式对象的 getter 函数时
// 只有在它们的对象被整个替换时才会触发回调
//  例:obj2.value = {val: 3}
// 传入 deep 选项即可创立深层侦听

// getter 函数
watch(() => obj2.value, (newVal, oldVal) => {
    // 留神此处的 newVal oldVal 的值是相等的
    // 除非替换掉整个 obj2.value
}, {deep: true   // 当值变更时触发回调})

// ref 创立的对象数据
watch(obj2, (newVal, oldVal) => {
    // 留神此处的 newVal oldVal 的值是相等的
    // 除非替换掉整个 obj2.value
}, {deep: true   // 当值变更时触发回调})

watchEffect 函数

和计算属性一样,不须要指定要侦听的响应式数据,而是会主动跟踪回调的响应式依赖,并在依赖变动时从新执行回调函数;
并且创立后回调会立刻执行一次 (不须要传入 immediate:true);
相比 watch 函数更加简洁不便。

import {ref, watchEffect} from 'vue';

const count = ref(0)

watchEffect(() => {console.log(count.value) // 0
})

进行侦听

当业务须要,或者在异步操作中创立侦听器时,
能够通过以下办法来进行侦听器。

const unwatch = watchEffect(() => {})

// 当不须要时调用 unwatch() 即可销毁侦听
unwatch()
setTimeout(() => {
  // 在同步中创立的侦听器在组件销毁时,主动进行,而异步中创立的不会!watchEffect(() => {})
}, 100)

DOM 更新后触发回调

侦听的数据源变更,有可能同时触发 vue 组件更新与侦听器回调。
默认状况下,回调会在组件更新之前执行, 也就是在回调中获取 dom 获取到的是 vue 组件 更新之前 的状态,
如果想要在回调中拜访 更新之后 的状态那么就须要传入 flush: ‘post’ 选项

watch(count, ()=>{

}, {flush: 'post'})

watchEffect(()=>{}, {flush: 'post'})

留神点

watch 函数的回调参数

回调函数的参数有两个,第一个为 ” 新值 ”, 第二个为 ” 旧值 ”, 如果只须要应用 ” 新值 ”, 能够疏忽第二个值,
如果监听的数据是对象,那么他们的 ” 新值 ” 与 ” 旧值 ” 是相等的,因为都指向同一个内存地址, 除非整个替换掉。

尽量不要在异步中创立侦听

尽量不要在异步中创立侦听,在异步中创立的侦听不会主动销毁,如果在异步中创立侦听,请手动完结侦听。

正文完
 0