乐趣区

关于javascript:vue3中的watch和watchEffect差异和使用

有四种类型的监听函数:watch / watchEffect / watchPostEffect / watchSyncEffect。

监听系统两个派别

能够分为两类 watch 和 watchEffect

watch

watch(监听对象, (旧状态, 新状态) => {...})

指定要监听的根本类型、数组等,但必须依据类型更改编写代码。
下一个状态,上一个状态,将传递要监听的值更改前后的值。

上面介绍如何形容受监听数据类型的差别。

(1) 根本类型 ref
const num = ref(0)
watch(num, (next, prev) => {console.log(next, prev);
})
(2) 数组
const arr = ref<number[]>([])
watch(() => [...arr.value], (next, prev) => {console.log(next, prev);
})
(3) 对象
const state = reactive({count : 0, age: 0})
watch(() => ({...state}), (next, prev) => {console.log(next, prev);
})

监听

数组能够一起传递多个元素,以监听多个元素。然而,有一个注意事项。

如果数组中传递的任何元素产生更改,则 watch 将触发,但如果 == 同时更改,则只触发一次 ==。

// 同时更改
const onClick = () => {
  ++num1.value
  ++num2.value
}

// 触发一次
watch([num1, num2], (next, prev) => {...})

在这种状况下,只需应用 async await 即可触发 2 次

const onClick = async () => {
  ++num1.value
  await nextTick()
  ++num2.value
}

watch([num1, num2], (next, prev) => {...})

监听嵌套对象(deep:true)

const state = reactive({
  age: 0,
  type: {hoge: 0}
})

watch(() => state, (next, prev) => {...}, {deep: true})

组件创立时立刻执行(immidiate:true)

immidiate: true如果为 true,则在创立组件时也会执行监听函数。

watchEffect

监听

立刻执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时从新运行该函数。

const count = ref(0)

watchEffect(() => console.log(count.value))
// -> logs 0

setTimeout(() => {
  count.value++
  // -> logs 1
}, 100)

进行监听

watchEffect 在组件的setup() 函数或生命周期钩子被调用时,侦听器会被链接到该组件的生命周期,并在组件卸载时主动进行。

在一些状况下,也能够显式调用返回值以进行侦听:

const stop = watchEffect(() => {/* ... */})

// later
stop()

革除副作用

当咱们组件卸载的时候, 清空监听函数或者定时器须要 onInvalidate

watchEffect(onInvalidate => {const token = performAsyncOperation(id.value)
  onInvalidate(() => {
    // id has changed or watcher is stopped.
    // invalidate previously pending async operation
    token.cancel()})
})

之所以是通过传入一个函数去注册生效回调,而不是从回调返回它,是因为返回值对于异步错误处理很重要。

在执行数据申请时,副作用函数往往是一个异步函数:

const data = ref(null)
watchEffect(async onInvalidate => {onInvalidate(() => {/* ... */}) // 咱们在 Promise 解析之前注册革除函数
  data.value = await fetchData(props.id)
})

副作用刷新机会

默认状况下,会在所有的组件 update 前执行:

watchEffect 0
onInvalidate 1
watchEffect 1
onUpdated

watchPostEffect 和 watchSyncEffect

有 3 种类型:1 预 (watchEffect)、2 同步(watchSyncEffect) 和 3 后(watchPostEffect)。
watchPostEffect 和 watchSyncEffect 是 watchEffect 的第二个参数的 == 刷新属性 ==。

watchEffect(() => {//},{flush: "sync" //or "post" or "pre"})

咱们将具体介绍每个执行工夫。

① pre(watchEffect)

这是默认值。在组件更新之前异步调用。
也就是说,在生命周期中,它在 onBeforeUpdate 之前调用

② sync(watchSyncEffect)

在组件更新之前或更新之前,立刻同步调用它。
然而,不倡议同步调用监督成果,因为它效率低下。
通常,它在 onBeforeUpdate 之前调用。

③ post(watchPostEffect)

在组件更新后调用。前更新更新到更新的计时。

程序
watchSyncEffect → watchEffect → onBeforeUpdate → watchPostEffect → onUpdated

注意事项

代码程序
watchEffect((onInvalidate) => {console.log("watchEffect", a.value);
});
let a = ref(0);

下面的代码会执行谬误, 而换成 watchPostEffect 就不会

异步操作
watchEffect((onInvalidate) => {const b = setTimeout(() => console.log(a.value));
  Promise.resolve().then(() => console.log(a.value));
});

扭转 a 的值, 不会触发打印

二者区别

watch 须要侦听 == 特定的数据源 ==,能够获取到前后值
watchEffect 则是获取

退出移动版