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

news2024/11/27 20:32:33

文章目录

  • 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.count2
      console.log(sum)
    })
    // 改变状态,输出  5
    state.count1++

    // 改变状态,输出 8
    state.count2 += 2
    return {
    }
  }
}
</script>

3 懒执行

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

const state = reactive({
   count: 2
 })
 watchEffect(() => {
   console.log(state.count)
 }, { lazy: true })
 // 改变状态,输出  2 3
 state.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.coloradmin.cn/o/1670989.html

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

相关文章

深度求索推出DeepSeek-V2:经济高效的多专家语言模型

AI苏妲己 深度求索发布了DeepSeek-V2混合专家&#xff08;MoE&#xff09;语言模型&#xff0c;每百万tokens&#xff0c;2元人民币价格&#xff0c;简直便宜到令人发指&#xff08;而且不是活动价格噢&#xff09;&#xff0c;可以说是继Groq以后&#xff0c;AI领域最惊艳的新…

PyQt:界面无边框+实现窗口最小化(任务栏图标隐藏+托盘图标显示)

一、整体实现效果 诸如WX、各种管家的桌面显示方式。窗口关闭后&#xff0c;往往是任务栏图标消失&#xff0c;保持右下角托盘图标显示&#xff0c;保持后台运行。双击托盘图标后&#xff0c;窗口显示。 二、代码实现 from PyQt5.QtWidgets import * from ato_upgrade impo…

植物ATAC-seq文献集锦(一)——基因组篇

ATAC-seq&#xff08;Assay for Transposase-Accessible Chromatin with high-throughput Sequencing&#xff09;是一种用于探究染色质开放性区域的技术&#xff0c;该技术利用Tn5转座酶接近核小体疏松区域切割暴露的DNA&#xff0c;获得开放的染色质区段(Open Chromatin)&…

快速判断出485从站设备是否支持MODBUS RTU无线通讯

对于变频器和仪表设备&#xff0c;都支持485串口通讯&#xff0c;那么怎么判断从站设备支持那种协议呢&#xff1f;通常分为两种方式去判断&#xff1a;1.从设备参数参看2.从设备通讯报文查看。本次文章以以台达MH300系列变频器为例。 1.从设备通讯参数查看 使用设备之前一定…

Apple store 静安·苹果店欣赏

官网&#xff1a; https://www.apple.com/today/Apple 亚洲第一大商店&#xff1a;Apple 静安零售店现已在上海开幕 静安苹果欣赏

智能体Agent笔记

智能体的定义&#xff1a; 1. 可以感受环境中的动态条件 2. 能采取动作影响环境 3. 能运用推理能力理解信息&#xff0c;解决问题&#xff0c;产生推断&#xff0c;决定动作。 我个人觉得智能体是个饼&#xff0c;最核心的问题是&#xff0c;你如何解决大模型的幻觉问题&…

【mysql】主从同步时出错,如何恢复同步

mysql主从同步出错&#xff0c;这个时候从服务器会停止同步服务&#xff0c;等待人工恢复&#xff0c;此时有多种方法来解决。 一、查看状态 在从服务器&#xff0c;登陆mysql&#xff0c;查询从服务器的状态&#xff1a; 从服务器mysql> show slave status\G 图1 可以看…

迪安诊断数智中心战略与PMO负责人徐黎明受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 迪安诊断技术集团股份有限公司数智中心战略与PMO负责人徐黎明先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“软件研发项目管理指标体系建设实践”。大会将于6月29-30日在北京举办&#xff0c;敬请关注&#xff01; …

Cocos 2048从创建到发布上线

一、制作2048小游戏过程 扫描体验2048小游戏 场景搭建&#xff0c;4X4棋盘和基础设置绘制背景板&#xff0c;包含预制体等信息考虑在棋盘中随机出现两个数字方块&#xff0c;数字为2&#xff0c;初始化操作滑动事件部分&#xff0c;让方块移动起来&#xff0c;每滑动一次就生成…

文本分类的深度注意图扩散网络 笔记

1 Title Deep Attention Diffusion Graph Neural Networks for Text Classification&#xff08;Yonghao Liu、Renchu Guan、Fausto Giunchiglia、Yanchun Liang、Xiaoyue Feng&#xff09;【EMnlp 2021】 2 Conclusion Text classification is a fundamental task with broad…

【刷题】一篇文章搞定“位运算”

只要春天不死&#xff0c;就有迎春的花朵年年岁岁开放&#xff0c;生命讲涅槃&#xff0c;生生不息&#xff0c;并会以另一种形式永存。 – 路遥 《平凡的世界》 (◦′ᆺ‵◦) ♬ ✧❥✧.•✧♡✧ ℒℴѵℯ ✧♡✧•.❥ (◦′ᆺ‵◦) ♬ ✧❥✧.•✧♡✧ ℒℴѵℯ ✧♡✧•.❥…

工作组PTH

文章目录 简述RID 500本地管理员密码喷洒何为RIP 500 安全标识符SID与RIDPTH为何必须是RID 500CrackMapExec进行密码喷洒 简述 在工作组PTH中为什么只有administrator账号可以,下面进行讲解与利用。RID 500本地管理员密码喷洒 何为RIP 500 安全标识符 安全标识符 安全标识符…

太速科技-基于VU3P的双路100G光纤加速计算卡

基于VU3P的双路100G光纤加速计算卡 一、板卡概述 基于Xilinx UltraScale16 nm VU3P芯片方案基础上研发的一款双口100 G FPGA光纤以太网PCI-Express v3.0 x16智能加速计算卡&#xff0c;该智能卡拥有高吞吐量、低延时的网络处理能力以及辅助CPU进行网络功能卸载的能力…

P5490.扫描线(python)

这个洛谷怎么对于python不太友好呢&#xff0c;没几次能全过的 本题使用扫描线的模板&#xff0c;首先把所有x坐标排序去重&#xff0c;放进列表X中。把所有横线lines排序。这样把所有矩阵都分成了块。对于每一块&#xff0c;高lines[i1]-lines[i]&#xff0c;宽就等于在这一块…

js图片回显的方法

直接上代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body>// HTML部分<input type"file" id"fileInput"><button onclick"show…

AI虚拟伴侣方案

打造类似Character AI的产品,现成的训练好的模型方案,适合做陪伴型虚拟女友等项目,近期看到的最佳项目: 1、项目背景: (1)项目动机:角色扮演LLM是AI的第二大消费用例,但通常被开源社区忽视。 (2)行业现状:缺乏与https://character.ai/提供的角色扮演LLM相对应的…

SpringBoot集成Curator实现Watch事件监听

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Zookeeper是一个Ap…

jenkis

文章目录 安装插件配置构建超时自动停止 安装插件 在线安装&#xff1a;安装jenkins后&#xff0c;初次启动的时候安装插件 在线安装&#xff1a;插件管理&#xff0c;可选插件中 离线安装&#xff1a;下载插件(.hpi格式) 使用该方法安装插件每次只能安装一个插件&#xff0c;…

软件设计中的数字:7

“ 使软件更易理解的秘密&#xff1a;米勒法则” 小游戏 学习之前先一起玩一个小游戏。 3秒钟时间&#xff0c;看看下面的图片中有多少个小块&#xff1f; 3秒到了&#xff0c;数出来了吗&#xff1f;22个。 没数出来也没关系&#xff0c;我也没数出来o(╥﹏╥)o 现在&…

CentOs搭建Kubernetes集群

kubeadm minikube 还是太“迷你”了&#xff0c;方便的同时也隐藏了很多细节&#xff0c;离真正生产环境里的计算集群有一些差距&#xff0c;毕竟许多需求、任务只有在多节点的大集群里才能够遇到&#xff0c;相比起来&#xff0c;minikube 真的只能算是一个“玩具”。 Kuber…