vue3语法watch与watchEffect

今天和各位大佬聊聊vue3的新增的钩子函数watchEffect与watch的区别与共同之处

我们一起回到梦开始的地方,用vue写一个简单的响应式计数器

大佬说这还用写,哈哈我们直接来看代码

js 复制代码
 <p>计数器:{{count}}</p>
<button @click="increment">+</button>
import {
  ref,
  watch,
  watchEffect
}

const count=ref(0)
const increment = ()=>{
  count.value++
}

但今天我们来对比学习一下watch与watchEff,所以我们再写一个计数器,并且分别调用这两个钩子函数

js 复制代码
 <p>计数器:{{count}}</p>
<button @click="increment">+</button>
  
<p>计数器二:{{count2}}</p>
<button @click="count2++">+</button>


const count=ref(0)
const count2=ref(0)
const increment = ()=>{
  count.value++
}
watch(count,(newValue,oldValue)=>{
  //state状态的改变
  console.log('count 改变了')
  console.log(newValue,oldValue)
  if(count.value>2){
    console.log('太大了')
  }
})

watchEffect(()=>{
  console.log(`count 的值是${count.value}`)
  console.log(`count2 的值是${count2.value}`)
})

我们来简单的看看watch函数接受的参数形式, count-响应式数据

回调函数()=>{},我们来简单说说这个newValue,oldValue,这两个变量从字面大佬应该一下猜到了,新的响应式数据和旧的响应式数据

待会儿我们还要说第三个能传进去的参数

我们来看看页面发生了什么

在我们没有点击页面的时候我们发现watchEffect函数直接执行了一次,但watch并没有,奇怪,好像组件生命周期的变化和这个钩子函数有关,没错,这就是一点不同

但是我们点击计数器1加号按钮后,当然,随着count的增大页面肯定打印了新旧count值,直到增大到2,控制台就会打印,太大了

这个大佬说,简单,不就监听这个响应式数据吗,watch和watchEffect都能实现监听,只不过watch和watchEffect的区别是一个不传参一个传参而言,对的,这就是我们要讲的第二个两者区别

我们再来看看计数器二的变化会导致两个钩子函数怎么运行,我们之后一直点击计数器二的加号,但是不点击计数器一

我们发现只有watchEffect函数运行了,所以答案显而易见,watchEffect函数会监听页面所有响应式数据的改变并执行,而watch需要配置被监听的数据

ok两点不同讲完两个不同点,我们来讲讲刚开始遗留的问题,watch函数能传的第三个参数是什么,没错就是 两个配置项 immediate和deep,这两个参数默认情况都是false我们直接手动演示一遍

js 复制代码
watch(count,(newValue,oldValue)=>{
  //state状态的改变
  console.log('count 改变了')
  console.log(newValue,oldValue)
  if(count.value>2){
    console.log('太大了')
  }
},{
  immediate:true,//默认是false,立即执行一次
  deep:false//深度监听,默认是false
})
//监听,订阅发布者模式,观察者模式
watchEffect(()=>{
  console.log(`count 的值是${count.value}`)
  console.log(`count2 的值是${count2.value}`)
})

这是更新后的watch函数与watchEffect

我们发现第一个配置参数 immediate决定了这个钩子函数是否在组件挂载后执行一次,因为默认是false,所有我们刚刚的代码并没有一开始就打印count改变了,但我们改为true后我们发现这个函数在过载后立马执行了一次

我们再来讲讲第二个配置参数deep,了解深浅拷贝的大佬应该 大概能猜出这个deep,没错深度监听,那什么叫深度监听呢

我们先不解释这个例子,我们直接上案例

js 复制代码
<p>计数器:{{count}}</p>
<button @click="increment">+</button>
  
<p>计数器二:{{count2}}</p>
<button @click="count2++">+</button>
 <br>
{{typeof user.age}}
<p>变化:{{user.age}}</p>
<!-- 这里用的是双向绑定,v-model.number 修饰符,限定输入框转换为为数字 -->
<input  v-model="user.age">
<p>变化:{{user.name}}</p>
<input type="text" v-model.number="user.name">
</div>


<script setup>
import BaseCard from './components/BaseCard.vue'
import Layout from './components/Layout.vue'
import {
  ref,
  watch,
  watchEffect
} from 'vue'
const count = ref(0)
const count2=ref(0)
//这里自动转化成reactive对象,响应式数据结构
const user=ref({
  name:'zhangsan',
  age:18
})
//count 改变后做点啥
const increment = ()=>{
  count.value++
}
watch(count,(newValue,oldValue)=>{
  //state状态的改变
  console.log('count 改变了')
  console.log(newValue,oldValue)
  if(count.value>2){
    console.log('太大了')
  }
},{
  immediate:true,//默认是false,立即执行一次
  deep:false//深度监听,默认是false
})
//监听,订阅发布者模式,观察者模式
watchEffect(()=>{
  console.log(`count 的值是${count.value}`)
  console.log(`count2 的值是${count2.value}`)
})
watch(user,(newValue,oldValue)=>{
  console.log(newValue)
  console.log(`user 的值是${user}`)//隐式类型转化
},{
  immediate:true,
  deep:true
})
</script>

依然是那个计数器,但我们来多了个复杂响应式对象,嘿嘿,这里还有一个小细节,大佬发现我们的user使用ref包裹的,但是,复杂响应式对象不因该用reatcive吗,其实这里是这样的,这个细节我们下面慢慢探讨

当您使用 ref 创建一个对象或数组时,Vue 实际上会在内部使用 reactive 来使该对象或数组成为响应式的。但是,您需要通过 .value 属性来访问或修改这个响应式数据。

我们把上述两个输入框的输入值双向设定在user这个响应式对象上,上面的 v-model.number其实是把输入框的默认字符串类型转换成number类型,大佬可以试试不加这个number,我们会发现屏幕上的{{typeof user.age}}变成了string

ok很牛逼 newValue是一个代理对象,而user是一个对象,这里涉及到ref的底层实现原理,我们后篇文章慢慢分析

那如果我们就是要看到user对象里的数据怎么办,没错JSON.stringify(user.value)

其实,上述的一切发生的原理都是建立在deep=true基础之上,为什么?其实这个时候大佬应该能大概了解深度监听是什么意思

我们来试试把deep改为false,这时我们无论怎么输入框改变user的值控制台都不会输出变化后的user对象,所有我们引出深度监听的概念

深度监听是 Vue.js 中用于监听复杂数据类型(如对象或数组)内部变化的机制。当对象或数组内部的属性或元素发生变化时,深度监听能够捕获这些变化,并触发相应的回调函数。

深度监听通常用于以下几种情况:

  • 当您需要监听一个对象内部多个属性的变化时。
  • 当您需要监听一个数组内部元素的添加、删除或更新时。

ok,我们试试最后一种情况,watchEffect能实现深度监听吗,我们来试试改变输入框的值,我们发现watchEffect还是自动执行了,我们来总结总结这两个钩子函数的区别

watch

  • 接受三个参数
  1. 监视的属性名 可以是单纯响应式数据也可以是响应式数组的某一个元素
  2. 监视的回调函数 可以拿到新旧值
  3. 配置项 immediate 立即执行一次回调函数 默认是false deep 深度监视,监听对象内部属性的变化

watchEffect

  1. 无需指定监视的属性名,在组件挂载前自动收集响应式依赖
  2. 不需要配置deep深度监听,因为会自动收集依赖
  3. 无需配置immediate,因为会自动执行
  4. 副作用函数执行时机:组件挂载前,依赖的响应式数据发生变化时
相关推荐
会说法语的猪6 分钟前
uniapp使用uni.navigateBack返回页面时携带参数到上个页面
前端·uni-app
林涧泣8 小时前
【Uniapp-Vue3】uni-icons的安装和使用
前端·vue.js·uni-app
雾恋8 小时前
AI导航工具我开源了利用node爬取了几百条数据
前端·开源·github
拉一次撑死狗9 小时前
Vue基础(2)
前端·javascript·vue.js
祯民9 小时前
两年工作之余,我在清华大学出版社出版了一本 AI 应用书籍
前端·aigc
热情仔9 小时前
mock可视化&生成前端代码
前端
m0_748246359 小时前
SpringBoot返回文件让前端下载的几种方式
前端·spring boot·后端
wjs04069 小时前
用css实现一个类似于elementUI中Loading组件有缺口的加载圆环
前端·css·elementui·css实现loading圆环
爱趣五科技9 小时前
无界云剪音频教程:提升视频质感
前端·音视频