vue3.0(八) 监听器(watch),高级监听器(watchEffect)

文章目录

  • watch
    • 1 watch的用法
    • 2 watch的高级用法
    • 3 watch性能优化
  • watchEffect
    • 1 停止监听
    • 2 侦听多个状态
    • 3 懒执行
  • watch和watchEffect的区别
  • watch和computed的区别


watch

watch特性进行了一些改变和优化。与computed不同,watch通常用于监听数据的变化,并执行一些副作用,侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。

1 watch的用法

  1. watch的基本用法
    watch(source, callback, options?)
    

    source表示要监听的数据,可以是一个响应式的数据对象、一个计算属性或一个方法的返回值;callback表示当数据发生变化时要执行的回调函数;options表示watch的一些配置选项,例如immediate、deep、flush等。

  2. 监听 ref 定义的响应式数据
    <template><div><div>值:{{count}}</div><button @click="add">改变值</button></div>
    </template><script>
    import { ref, watch } from 'vue'
    export default {setup () {const count = ref(0)const add = () => {count.value++}watch(count, (newVal, oldVal) => {console.log('值改变了', newVal, oldVal)})return {count,add}}
    }
    </script>
    
    上述代码执行效果
  3. 监听 reactive 定义的响应式数据
    <template><div><div>姓名:{{ obj.name }}</div><div>年龄:{{ obj.age }}</div><button @click="changeName">改变值</button></div>
    </template><script>
    import { reactive, watch } from 'vue'
    export default {setup () {const obj = reactive({name: 'zs',age: 14})const changeName = () => {obj.name = 'ls'}watch(obj, (newVal, oldVal) => {console.log('值改变了', newVal, oldVal)})return {obj,changeName}}
    }
    </script>
    

上述代码执行结果
注:此处监听的新值和旧值相同,主要是因为新旧值引用地址是相同的,
此处可采取computed计算属性先实现深拷贝。

	<template><div><div>姓名:{{ obj.name }}</div><div>年龄:{{ obj.age }}</div><button @click="changeName">改变值</button></div></template><script>import { reactive, watch, computed } from 'vue'export default {setup () {const obj = reactive({name: 'zs',age: 14})const changeName = () => {obj.name = 'ls'}const deepObj = computed(() => {return JSON.parse(JSON.stringify(obj))})watch(deepObj, (newVal, oldVal) => {console.log('值改变了', newVal, oldVal)})return {obj,changeName}}}</script>
  1. 监听多个ref的值,采用数组形式
    <template><div><!-- 侦听多个变量 -->姓名:<input v-model="userName" type="text">年龄:<input v-model="age" type="number"></div>
    </template>
    <script lang="ts">
    import { defineComponent, ref, watch } from 'vue'
    export default defineComponent({setup () {const userName = ref<string>('张三')const age = ref<number>(18)watch([userName, age], (newVal, oldVal) => {console.log(newVal, oldVal)})return {userName,age}}
    })
    </script>
    

在这里插入图片描述

  1. 监听reactive对象中某个属性的变化
    <template><div><div>{{obj.name}}</div><div>{{obj.age}}</div><button @click="changeName">改变值</button></div>
    </template><script>
    import { reactive, watch } from 'vue'
    export default {setup () {const obj = reactive({name: 'zs',age: 14})const changeName = () => {obj.age++}watch(() => obj.age, (newVal, oldVal) => {console.log(newVal, oldVal)})return {obj,changeName}}
    }
    </script>
    

在这里插入图片描述

2 watch的高级用法

  1. 一次性监听
    每当被侦听源发生变化时,侦听器的回调就会执行。如果希望回调只在源变化时触发一次,请使用 once: true 选项。
    <template><div><div>{{obj.name}}</div><div>{{obj.classInfo.studentNum}}</div><button @click="changeName">改变值</button></div>
    </template><script>
    import { reactive, watch } from 'vue'
    export default {setup () {const obj = reactive({name: 'zs',age: 14,classInfo: {className: '一年级',studentNum: 45}})const changeName = () => {obj.classInfo.studentNum++}watch(() => obj, (newVal, oldVal) => {console.log(newVal, oldVal)}, {once: true})return {obj,changeName}}
    }
    </script>
    
  2. 深层侦听器
    直接给 watch() 传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发:deep 选项,强制转成深层侦听器:
    <template><div><div>{{obj.name}}</div><div>{{obj.classInfo.studentNum}}</div><button @click="changeName">改变值</button></div>
    </template><script>
    import { reactive, watch } from 'vue'
    export default {setup () {const obj = reactive({name: 'zs',age: 14,classInfo: {className: '一年级',studentNum: 45}})const changeName = () => {obj.classInfo.studentNum++}watch(() => obj, (newVal, oldVal) => {console.log(newVal, oldVal)}, {deep: true // 不添加deep属性,watch不会触发})return {obj,changeName}}
    }
    </script>
    

    注意:当我们使用deep选项时,watch的性能会受到一定的影响,因为Vue需要对对象或数组进行递归遍历。因此,只有在必要的情况下才应该使用deep选项

  3. 即时回调的侦听器
    watch 默认是懒执行的:仅当数据源变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。举例来说,我们想请求一些初始数据,然后在相关状态更改时重新请求数据。通过传入 immediate: true 选项来强制侦听器的回调立即执行:
    import { reactive, watch } from 'vue'
    const state = reactive({count: 2
    })
    watch(() => state.count,(newVal, oldVal) => {console.log(newVal, oldVal)},{ immediate: true }
    )
    
  4. flush 回调的触发时机
  • sync:同步模式下执行
  • pre:在数据变化之前执行回调函数
  • post:在数据变化之后执行回调函数,但是需要等待所有依赖项都更新后才执行
    import { reactive, watch } from 'vue'
    const state = reactive({count: 2
    })
    watch(() => state.count,(newVal, oldVal) => {console.log(newVal, oldVal)},{ flush: sync }
    )
    

3 watch性能优化

  1. 使用computed代替watch
    import { reactive, computed } from 'vue'
    const state = reactive({count: 2
    })const doubleCount = computed(() => {return state.count * 2
    })
    console.log(doubleCount.value) // 输出:2
    state.count++
    console.log(doubleCount.value) // 输出:4
    
  2. 使用throttle和debounce控制回调函数的执行频率
    频繁地监听一个值的变化,并在变化时执行一些操作。如果回调函数执行的太频繁,会影响性能。为了避免这种情况,我们可以使用throttle和debounce控制回调函数的执行频率
    throttle可以用于控制函数在一定时间内只能执行一次,
    debounce可以用于控制函数在一定时间内不会连续执行
    import { reactive, watch } from 'vue'
    import { throttle } from 'lodash-es'
    const state = reactive({count: 3
    })
    watch(() => state.count,throttle((newVal, oldVal) => {console.log(newVal, oldVal)}, 1000)
    )
    state.count++
    

watchEffect

watchEffect 函数来创建高级侦听器。与 watch 和 computed 不同,
watchEffect 不需要指定依赖项,自动追踪响应式状态的变化,并在变化时重新运行

<template><div><div>{{obj.name}}</div><div>{{obj.age}}</div><button @click="changeAge">改变值</button></div>
</template>
<script>
import { reactive, watch, watchEffect } from 'vue'
export default {setup () {const obj = reactive({name: 'zs',age: 14,})const changeName = () => {obj.age++}watchEffect(() => {console.log(obj.age)})return {obj,changeAge}}
}
</script>

1 停止监听

watchEffect 函数不会返回一个停止侦听的函数。如果我们需要停止侦听,我们可以将 watchEffect 的返回值设为 null

const stop = watchEffect(() => {})// 当不再需要此侦听器时:
stop()

2 侦听多个状态

如果需要侦听多个响应式状态,可以在 watchEffect 函数中使用这些状态,并在函数中返回一个计算值,

<script>
import { reactive, watchEffect } from 'vue'
export default {setup () {const state = reactive({count1: 2,count2: 3})watchEffect(() => {const sum = state.count1 + state.count2console.log(sum)})// 改变状态,输出  5state.count1++// 改变状态,输出 8state.count2 += 2return {}}
}
</script>

3 懒执行

watchEffect 函数也支持懒执行(lazy evaluation)。如果我们将 watchEffect 的第二个参数设置为 { lazy: true },则这个函数会在第一次访问响应式状态时才会被运行

const state = reactive({count: 2})watchEffect(() => {console.log(state.count)}, { lazy: true })// 改变状态,输出  2 3state.count++

watch和watchEffect的区别

watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:
watch 监听函数可以添加配置项,也可以配置为空,配置项为空的情况下,
watch的特点为:

  • 有惰性:运行的时候,不会立即执行;
  • 更加具体:需要添加监听的属性;
  • 可访问属性之前的值:回调函数内会返回最新值和修改之前的值;
  • 可配置:配置项可补充 watch 特点上的不足:
  • immediate:配置 watch 属性是否立即执行,值为 true 时,一旦运行就会立即执行,值为 false时,保持惰性。
  • deep:配置 watch 是否深度监听,值为 true 时,可以监听对象所有属性,值为 false 时保持更加具体特性,必须指定到具体的属性上。
    watchEffect 特点
  • 非惰性:一旦运行就会立即执行;
  • 更加抽象:使用时不需要具体指定监听的谁,回调函数内直接使用就可以;
  • 不可访问之前的值:只能访问当前最新的值,访问不到修改之前的值;

watch和computed的区别

computed(计算属性):

  1. 定义:computed是一个基于其依赖的数据进行计算的值,可以缓存计算的结果。
  2. 工作原理:Vue会自动追踪computed属性方法对data的数据依赖,并在依赖数据发生变化时重新计算computed属性的值。
    computed特点:
    • 支持缓存,只有依赖数据发生改变时才会重新进行计算。
    • 不支持异步操作,如果computed内有异步操作,则无效。
    • 必须通过return返回一个值。
    • 适合当一个属性受多个属性影响时使用。
    • 在模板中可以直接使用,访问时不需要加括号。
      watch(监听):
  3. 定义:watch用于监听响应式数据的变化,并在数据发生变化时执行一些自定义的操作。
  4. 工作原理:当监听的数据发生变化时,会直接触发相应的操作。
    watch特点:
    • 不支持缓存功能,监听的数据发生变化时会直接触发相应的操作。
    • 支持异步操作,适合监听路由和设置计时器等。
    • 可以没有返回值。
    • 适合当一条数据影响多条数据时使用。
    • 在模板中不能直接使用,需要通过事件或方法进行调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1421695.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式-工厂模式设计与详解

一、设计模式介绍 设计模式是我们开发中常常需要面对的核心概念&#xff0c;它们是解决特定问题的模板或者说是经验的总结。这些模式被设计出来是为了让软件设计更加清晰、代码更加可维护且能应对未来的变化。良好的设计模式不仅能解决重复代码的问题&#xff0c;还能使团队中…

object.key()用法

object.key(obj) 一、概念&#xff1a;返回一个由一个给定对象的自身可枚举属性组成的数组。 二、用法&#xff1a; 1、参数为对象&#xff1a;则返回为 对象属性名组成的数组。 let obj {日期&#xff1a;date,姓名&#xff1a;userName,地址:address}console.log(Object.k…

作业帮重启k12,保底年薪150万。。。

作业帮 近期&#xff0c;一位学而思前员工在脉脉上爆料发问&#xff1a; 收到猎头电话&#xff0c;说作业帮重启 K12&#xff0c;K12 主讲无责保底年薪 150W&#xff0c;base 北京。 楼下评论区一位新东方在职员工表示&#xff0c;似乎有这事儿&#xff1a; 而另外一个网友则表…

WordPress/Typecho 站点使用 CloudFlare 后优化加速方法以及注意事项

目前很多 WordPress 站长都盲目的认为使用了 CloudFlare 后,站点速度明显感觉慢了很多,加上一些别有用心的人(有些人就是这么不喜欢 CloudFlare,你品,你细品!) 再制作一个使用 CloudFlare 站点的测速结果截图,让很多 WordPress 新手站长们谈 CloudFlare 色变。其实大家…

Android Studio开发之路(十)app中使用aar以及报错记录

书接上文&#xff1a;Android Studio开发之路&#xff08;九&#xff09;创建android library以及生成aar文件 五、app中使用aar文件的方法 先复制一下上面生成的aar文件。然后在你要添加到的app左上角选择“project”模式&#xff0c;然后找到libs文件夹&#xff0c;点击右键…

#初阶模板

目录 1.泛型编程 2.模板 &#xff08;1&#xff09;函数模板 &#xff08;2&#xff09;举个栗子&#xff08;模板的使用&#xff09; 1.模板的声明有两种形式 2.函数模板的原理 &#xff08;3&#xff09;模板参数的匹配原则 &#xff08;4&#xff09;类模板 类模板…

探索免费静态IP海外的奥秘

在数字化时代&#xff0c;网络资源的获取和利用对于个人和企业都至关重要。其中&#xff0c;独立静态IP地址更是因其稳定性和安全性备受青睐。本文将带您深入了解“免费的独立静态IP海外”的奥秘&#xff0c;探讨其背后的原理、优势、获取途径以及使用场景。 一、独立静态IP的基…

Kubernetes的Pod控制器深度解析

1.1 Pod控制器介绍 在Kubernetes中&#xff0c;Pod是最小的管理单元&#xff0c;用于运行容器。根据Pod的创建方式&#xff0c;可以将其分为两类&#xff1a; 自主式Pod&#xff08;Stateless Pods&#xff09;&#xff1a;这些Pod是直接由用户或管理员创建的&#xff0c;通常…

GPT搜索鸽了!改升级GPT-4

最近OpenAI太反常&#xff0c;消息一会一变&#xff0c;直让人摸不着头脑。 奥特曼最新宣布&#xff1a;5月13日开发布会&#xff0c;不是GPT-5&#xff0c;也不是盛传的GPT搜索引擎&#xff0c;改成对ChatGP和GPT-4的升级&#xff5e; 消息一出&#xff0c;大伙儿都蒙了。 之…

STM32_HAL_系统定时器(SysTick)_实现计时

1介绍 系统定时器&#xff08;SysTick&#xff09;是ARM Cortex-M处理器系列中的一个特殊定时器&#xff0c;它不属于STM32F1系列微控制器的外设&#xff0c;而是处理器内部的一个组件。SysTick定时器的作用是为操作系统或其他需要精确时钟计数和中断服务的应用提供基础的时间…

【Linux】自动化构建工具make/Makefile和git介绍

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12625432.html 目录 前言 Linux项目自动化构建工具-make/Makefile 举例 .PHONY 常见符号 依赖关系…

05、 java 的三种注释及 javadoc 命令解析文档注释(即:java 特有注释方式)的过程

java的三种注释 1、单行注释&#xff1a;其一、代码展示&#xff1a;其二、特点&#xff1a; 2、多行注释&#xff1a;其一、代码展示&#xff1a;其二、特点&#xff1a; 3、文档注释(java特有)&#xff1a;其一、代码展示&#xff1a;其二、注释文档的使用&#xff1a;其三、…

基础ArkTS组件:数据面板组件(图表),日期选择器组件(HarmonyOS学习第三课【3.5】)

tuoz数据面板组件 DataPanel 数据面板组件&#xff0c;用于将多个数据占比情况使用占比图进行展示。 说明 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 DataPanel(options:{values: numbe…

开关电源功率测试方法:输入、输出功率测试步骤

在现代电子设备中&#xff0c;开关电源扮演着至关重要的角色&#xff0c;其效率和稳定性直接影响到整个系统的性能。因此&#xff0c;对开关电源进行功率测试成为了电源管理的重要环节。本文将详细介绍如何使用DC-DC电源模块测试系统对开关电源的输入输出功率进行准确测量&…

如何使用Docker安装并运行Nexus容器结合内网穿透实现远程管理本地仓库

前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊如何使用Docker安装并运行Nexus容器结合内网穿透实现远程管理本地仓库&#xff0c;希望大家能觉得实用&#xff01; 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496…

2024 银行从业资格证考试备考资料及备考群

2024 银行从业资格证考试备考资料 2024 年 06月1、2日 银行从业资格考试全国统一考试&#xff08;统考&#xff09; 有没有小伙伴在准备备考的&#xff0c;不知道大家都准备怎么学习呢&#xff0c;这里我整理了一些免费备考资料&#xff0c;含【三色笔记】&#xff0c;供大家…

Spring解决泛型擦除的思路不错,现在它是我的了。

你好呀&#xff0c;我是浮生。 Spring 的事件监听机制&#xff0c;不知道你有没有用过&#xff0c;实际开发过程中用来进行代码解耦简直不要太爽。 但是我最近碰到了一个涉及到泛型的场景&#xff0c;常规套路下&#xff0c;在这个场景中使用该机制看起来会很傻&#xff0c;但…

CoSeg: Cognitively Inspired Unsupervised Generic Event Segmentation

名词解释 1.特征重建 特征重建是一种机器学习中常用的技术&#xff0c;通常用于自监督学习或无监督学习任务。在特征重建中&#xff0c;模型被要求将输入数据经过编码器&#xff08;encoder&#xff09;转换成某种表示&#xff0c;然后再经过解码器&#xff08;decoder&#x…

中学数学研究杂志中学数学研究杂志社中学数学研究编辑部2024年第4期目录

教学纵横 高中数学选择性必修课程函数主线分析 柳双;吴立宝; 1-4 贯彻新课程理念 促学习能力提升——以“三角函数诱导公式”教学为例 陆雨轩; 4-6《中学数学研究》投稿&#xff1a;cn7kantougao163.com 对高中数学新课标教材新增知识点的价值分析 钱伟风;刘瑞美; …

商务分析方法与工具(十):Python的趣味快捷-公司财务数据最炫酷可视化

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…