vue3中watch和watchEffect用法与区别

vue3中watch和watchEffect用法与区别

两个都是vue3中的监听器,监听数据时使用

watch

基本用法

当我们需要在数据变化时执行一些"副作用":如更改 DOM、执行异步操作,我们可以使用 watch 函数。 watch默认初始不执行 ,需要修改immediate为true,来配置。该函数接收三个属性,监听数据源、回调函数、配置项

ini 复制代码
let num1 = ref(1)
let num2 = ref(2)
let sum = computed(()=>num1+num2)
let obj = reactive({name:'zy',age:"20",info:{job:'web'}})

监听数据源

接收的参数可以为 1.ref声明

javascript 复制代码
watch(num,(newVal)=>{
	console.log(num,newVal)
})

2.reavite声明 监听obj 不能监听obj.name

javascript 复制代码
watch(obj,(newVal,oldVal)=>{
//任一属性更改触发
	console.log(oldVal,newVal)
	// 注意:`newVal` 此处和 `oldVal` 是相等的
})

3.一个getter函数的值

javascript 复制代码
// getter 函数
watch(
  () => num1.value + num2.value,
  (sum) => {
    console.log(`sum of num1 + num2 is: ${sum}`)
  }
)

4.computed的值

javascript 复制代码
// 计算属性
watch(sum, (newValue) => {
  console.log(`sum is ${newValue}`)
})

5.以上类型值得集合

javascript 复制代码
/ 以上类型的值组成的数组
watch([num1, () => num2.value], ([newX, newY]) => {
  console.log(`num1 is ${newX} and num2 is ${newY}`)
})

注意

传入getter函数时只有在对象被替换时才会触发:

php 复制代码
const obj = reactive({
  someString: 'hello',
  someObject: { count: 0 }
})

watch(
  () => obj.someObject,
  () => {
    // 仅当 obj.someObject 被替换时触发
  }
)

当然,你也可以显式地加上 deep 选项,强制转成深层侦听器:

javascript 复制代码
	watch(
	  () => obj.someObject,
	  (newValue, oldValue) => {
	    // `newValue` 此处和 `oldValue` 是相等的
	    // 除非 obj.someObject 被整个替换了
	    console.log('deep', newValue.count, oldValue.count)
	  },
	  { deep: true }
	)
	
	obj.someObject.count++ // deep 1 1

深层侦听一个响应式对象或数组,新值和旧值是相等的。为了解决这个问题,我们可以对值进行深拷贝。

javascript 复制代码
watch(
  () => _.cloneDeep(obj.someObject),
  (newValue, oldValue) => {
    // 此时 `newValue` 此处和 `oldValue` 是不相等的
    console.log('deep', newValue.count, oldValue.count)
  },
  { deep: true }
)

	obj.someObject.count++ // deep 1 0

深层侦听需要遍历所有嵌套的属性,当数据结构庞大时,开销很大。所以我们要谨慎使用,并且留意性能。

回调函数

数据发生变化时执行回调函数。 回调函数中可以接收三个参数:新值、旧值、清除副作用的回调函数,该回调函数会在副作用下一次执行前调用,可以用来清除无效的副作用,如等待中的异步请求:

scss 复制代码
const id = ref(1)
const data = ref(null)

watch(id, async (newValue, oldValue, onCleanup) => {
  const { response, cancel } = doAsyncWork(id.value)
  // `cancel` 会在 `id` 更改时调用
  // 以便取消之前未完成的请求
  onCleanup(cancel)
  data.value = await response.json()
})

watch 有返回值,返回值是一个用来停止该副作用的函数

scss 复制代码
const unwatch = watch(() => {})
// 当该侦听器不再需要时调用
unwatch()

配置选项

第三个参数是一个可选的对象,支持以下选项: immediate :在侦听器创建时立即触发回调。 deep :深度遍历,以便在深层级变更时触发回调。 flush :回调函数的触发时机。pre:默认,dom 更新前调用,post: dom 更新后调用,sync 同步调用。 onTrack / onTrigger:用于调试的钩子。在依赖收集和回调函数触发时被调用。

watchEffect

基本用法

watch每次初始化会加载一次,不用指定监听源,自动收集依赖,只要在回调中引用到了响应式的属性,只要这些属性发生改变,回调就会执行。

接受两个参数,第一个参数是数据发生变化时执行的回调函数,用法和 watch 一样。第二个参数是一个可选的对象,支持 flush 和 onTrack / onTrigger 选项,功能和 watch 相同。

补充:如果我们想要在回调函数里面获取更新后的 DOM,我们需要给监听器多传递一个参数选项即可:flush: 'post'。,但是 Vue3 单独给 watchEffect 提供了一个更方便的方法,也可以叫做 watchEffect 的别名,代码如下:

arduino 复制代码
watch(source, callback, {
  flush: 'post'
})
watchEffect(callback, {
  flush: 'post'
})

注意:使用同步语句创建的侦听器,会自动绑定到宿主组件实例上,并且会在宿主组件卸载时自动停止。使用异步回调创建一个侦听器,则不会绑定到当前组件上,你必须手动停止它,以防内存泄漏。如下面这个例子:

xml 复制代码
<script setup>
import { watchEffect } from 'vue'

// 组件卸载会自动停止
watchEffect(() => {})

// 组件卸载不会停止!
setTimeout(() => {
  watchEffect(() => {})
}, 100)
</script>
scss 复制代码
const unwatch = watchEffect(() => {})
// ...当该侦听器不再需要时
unwatch()

总结

watch 和 watchEffect 的主要功能是相同的,都能响应式地执行回调函数。它们的区别是追踪响应式依赖的方式不同:

1.watch 只追踪明确定义的数据源,不会追踪在回调中访问到的东西;默认情况下,只有在数据源发生改变时才会触发回调;watch 可以访问侦听数据的新值和旧值。

2.watchEffect 会初始化执行一次,在副作用发生期间追踪依赖,自动分析出侦听数据源;watchEffect 无法访问侦听数据的新值和旧值。 简单一句话,watch 功能更加强大,而 watchEffect 在某些场景下更加简洁。

相关推荐
别拿曾经看以后~20 分钟前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死23 分钟前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人34 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人35 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR40 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香42 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍