Vue3 —— watch 监听器及源码学习

这篇具有很好参考价值的文章主要介绍了Vue3 —— watch 监听器及源码学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • 该文章是在学习 小满vue3 课程的随堂记录
  • 示例均采用 <script setup>,且包含 typescript 的基础用法

前言

在 vue3 中,必须是 refreactive 包裹起来的数据,才可以被 watch 监听到

一、基本使用

1、语法:watch(source, cb, options)

  • source 是监听的目标,有 4 种书写形式:
    • reactive 形式的响应式数据
    • ref 形式的响应式数据
    • 数组形式:监听多个响应式数据时(应该用的不多)
      • 挨个放进 数组 里,如 [响应式数据1, 响应式数据2]
      • cb 对应的 函数参数(新值、旧值)也都是 数组 形式,详见例子
    • 函数形式:若只想监听 reactive 深层中指定属性,该指定属性是
      • 引用类型,不需要函数形式,直接 obj.a.b
      • 非引用类型,比如是一个字符串,则需要使用 函数形式 返回,详见例子
  • cb 是回调函数,(newVal,oldVal) => {}
  • options 是配置项
    • deep: 是否开启深层监听
      • reactive 类型的数据 不需要开启,源码中已做了深层响应式
      • ref 类型的数据如果需要监听到深层,要设置为 true(虽然监听到深层,但是 source 不能指定到深层)
    • immediate: 是否立刻执行
    • flush: watch 的执行顺序。
      • pre 组件更新之前执行(默认)
      • sync 同步执行;
      • post 组件更新之后执行

2、例子

下面代码中,演示了多个情景下的使用

<input type="text" v-model="xiaoman1" />
<br />
<input type="text" v-model="xiaoman2" />
<br />
<input type="text" v-model="message.foo.bar" />
<br />
<input type="text" v-model="message2.foo.bar" />
const xiaoman1 = ref<string>("小满1");
const xiaoman2 = ref<string>("小满2");

const message = ref({
  foo: {
    bar: "aaaaa",
  },
});

const message2 = reactive({
  foo: {
    bar: "aaaaa",
  },
});

watch(xiaoman1, (newVal, oldVal) => {
  console.log("监听单个数据源", newVal, oldVal);
});

// 用数组监听多个数据源,[新值数组], [旧值数组]
watch([xiaoman1, xiaoman2], (newVal, oldVal) => {
  console.log("用数组监听多个数据源,[新值数组], [旧值数组]", newVal, oldVal);
});

// ref 深层监听
watch(
  message,
  (newVal, oldVal) => {
    // 如果是引用类型,新值 和 旧值 是一样的
    console.log("ref 深层监听&立刻执行", newVal, oldVal);
  },
  {
    deep: true, // 深度监听,ref 若需要深度监听,这里要开启
    immediate: true, // callback 立刻先执行一次
    flush: "pre", // 【watch的执行顺序】 pre 组件更新之前调用(默认);sync 同步执行;post 组件更新之后执行
    // flush 属性在 watch 中用的不多,watchEffect中可能用到
  }
);

// reactive 深层监听:不必开启深度监听
watch(
  message2,
  (newVal, oldVal) => {
    // 如果是引用类型,新值 和 旧值 是一样的
    console.log("reactive 深层监听&立刻执行", newVal, oldVal);
  },
  {
    // deep: true, // reactive 不必开启深度监听,源码已做了深层监听
    // immediate: true,
  }
);

// 若只想监听 reactive 深层中的单个属性,(第一个参数)引用类型可直接写,否则使用函数形式
watch(
  message2.foo, // 监听到 foo,foo是引用类型,直接写就行
  // () => message2.foo.bar, // 监听到 bar,需要用函数形式

  (newVal, oldVal) => {
    // 如果是引用类型,新值 和 旧值 是一样的
    console.log("reactive 监听深层中的单个属性", newVal, oldVal);
  }
);

二、源码学习

由于源码较多,这里不做截图文章来源地址https://www.toymoban.com/news/detail-653048.html

/**
 * 

 * @vue/runtime-core/runtime-core.cjs.prod.js 搜索 function watch
 *
 * -  watch(source, cb, options)
 *
 * -  source 有很多种类型,reactive、ref、数组、函数,所以先判断类型,格式化source
 *    - ref 类型,直接把 value 取出来,赋值给 getter
 *    - reactive 类型,直接把整体赋值给 getter,deep 手动置为 true 即可(reactive已经进行了深度监听)
 *    - 数组类型,做遍历,对每一项再判断类型,分别处理完之后丢进新数组返回
 *          - ref类型,返回.value
 *          - reactive类型,递归处理后返回
 *          - 函数的话,进行加工
 *    - 函数类型
 *          - 判断有没有 cb
 *              - 有 cb 的话,同样也是对函数做了加工赋值给 getter
 *              - 没有 cb,走进 watchEffect(下一章)
 *
 * - deep处理:
 *          - cb、deep 若同时存在,即 有回调函数 且设置了 深度监听,进行 traverse 递归深度监听(当然是更耗时的)
 *
 * - flush处理:先初始化出 scheduler 调度器
 *          - sync 同步执行,scheduler = job
 *          - post 组件更新后,将 job 通过 queuePostRenderEffect 函数处理后再赋值给 scheduler
 *                  - 注意,源码中看到 queuePostRenderEffect 这个函数,一定表示是在组件更新之后再去执行
 *          - pre 组件更新前,queueJob 处理 job 后赋值给 scheduler
 *
 * - ReactiveEffect 收集依赖更新:
 *          - 上面步骤 将 getter、scheduler处理好后作为参数 给到 ReactiveEffect 函数
 *          - ReactiveEffect 收集好依赖之后,有更新的话 就会触发 scheduler,也就是说会执行 job
 *
 *
 * - cb 存在
 *          - immediate 为 true 时,会立即调用一下 job
 *                - 内部会先获取到新值 newVal
 *                - 如果是第一次执行,旧值 oldVal 会置为 undefined
 *                - (执行完这里才会更新)然后 把新值赋值给旧值,为下一次使用准备 (所以如果是对象,新旧值是相等的)
 *          - immediate 为 false 时,
 *                - 先给旧值做初始化,如 oldVal = '小满'
 *                - 依赖如果更新,会触发 scheduler,执行 job
 *                      - job 内新值 newVal = '小满1'
 *                      - 旧值 oldVal 不会走进 undefined,会等于原有的 oldVal = '小满'
 *                      - (执行完这里才会更新)会把 oldVal = '小满1'
 *
 *
 */

到了这里,关于Vue3 —— watch 监听器及源码学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3:计算属性、监听器

    计算属性是指 基于现有状态派生 (演变) 出新的状态,现有状态发生变化,派生状态重新计算。 computed 接收回调函数作为参数,基于回调函数中使用的响应式数据进行计算属性的创建,回调函数的返回值就是基于现有状态演变出的新状态。 完整写法 案例:动态显示名字。

    2024年02月09日
    浏览(85)
  • 【源码系列#04】Vue3侦听器原理(Watch)

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数 第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性

    2024年02月04日
    浏览(60)
  • 【Vue2从入门到精通】Vue监听器watch,计算属性computed,方法methods的区别及使用场景

    ✍创作者:全栈弄潮儿 🏡 个人主页: 全栈弄潮儿的个人主页 🏙️ 个人社区,欢迎你的加入:全栈弄潮儿的个人社区 📙 专栏地址:vue2从入门到精通 【分享几个国内免费可用的ChatGPT镜像】 【10几个类ChatGPT国内AI大模型】 【用《文心一言》1分钟写一篇博客简直yyds】 【用

    2023年04月15日
    浏览(45)
  • watch监听器三种监听方式

    1、普通监听( 无法监听到第一次绑定的变化 ) 这样使用watch时有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。 2、普通监听( 可以监听到第一次绑定的变化) 给 text 绑定了一个handler方法,之前我们写的 watch 方法其实默认写的就是

    2024年02月15日
    浏览(40)
  • Vue3前端开发,watch数据侦听器的立即执行

    Vue3前端开发,watch数据侦听器的立即执行!实际上,我们可以通过回调函数的后面,再追加一个对象,来设置这个参数,immediate:true.来实现一种立即执行的效果。在页面记载完成后,马上就会执行一次watch. 如上所示,我们在回调函数的后面,追加了一个参数,是一个对象类型

    2024年01月18日
    浏览(47)
  • vue3 watch 监听多值以及深度监听用法

    1.监听单个值 引入: import {…, watch} from “vue”; import {useRouter} from ‘vue-router’; 2.监听多个值 还是上面路由的例子 2.深度监听

    2024年02月14日
    浏览(52)
  • Vue3 计算属性和侦听器实战(computed、watch)——简易点餐页面

    这篇文章记录一下 Vue3 计算属性和侦听器 (computed、watch) 实战的内容,这篇文章我们在有计算属性和侦听器的基础上,我们来制作一个简易点餐页面,接下来我们一起来从零到一开始制作。 计算属性和侦听器相关文章推荐: 深入与浅谈 Vue 中计算属性和侦听器的区别和使用

    2024年02月09日
    浏览(97)
  • 微信小程序 - 最新超详细 watch 侦听器功能,支持监听对象、数组及各种复杂对象数据,可在任意页面或组件中使用(绝非网上千篇一律的 “setWatcher“ 不能监听对象的垃圾方法,方案开箱即用)

    网上的教程全都是一摸一样的 setWatcher(this) 方案,重要的是这种方案不能监听对象,可以说一无是处。 本文 在微信小程序中实现 watch 监听器监听数据的功能,让小程序拥有 watch 监听对象、数组等复杂数据变化的能力, 您按照教程几分钟就能搞定,保证 100% 好用且使用方法

    2024年02月11日
    浏览(105)
  • Vue3 watch 监听对象数组中对象的特定属性

    在 Vue 3 中,可以使用 watch 函数来监听对象数组中对象的特定属性。可以通过在回调函数中遍历数组来检查对象的特定属性是否发生变化,并在变化发生时执行相应的操作。 例如,假设有一个名为 items 的对象数组,其中每个对象都有一个名为 checked 的布尔属性和一个名为 n

    2023年04月20日
    浏览(41)
  • vue3中用watch监听响应式数据的注意点

    如果你在vue3中使用reactive()方法创建响应式数据,然后又用torefs()方法将响应式数据解构成单一的ref响应式数据。 此时,如果你想用watch监听解构出来单一的响应式数据,watch不起作用。 此时,你需要用watch监听之前的reactive()方法创建的数据,这样是能监听到的,要开启深度监

    2024年02月13日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包