Vue3源码解析watch函数实例

yizhihongxing

Vue3源码解析watch函数实例

在Vue3.x中,watch函数作为一个重要的API存在,它能够对一个值进行监测,当这个值发生变化时,就可以执行相关的回调函数。本文将分享一个完整的攻略,来解析Vue3源码中watch函数的实现。

1. watch函数的基本用法

在Vue3.x中,watch函数的基本用法如下:

// 监听一个值
watch(
  // 被监听的值的getter函数,以响应式的方式进行监听
  () => count,

  // 当值发生变化时,执行的回调函数
  (newVal, oldVal) => {
    console.log(`count由${oldVal}变为${newVal}`)
  }
)

基本上,watch函数就是把我们之前在Vue2.x中使用的$watch API包装一下,让其更加灵活,并且可以自由组合使用。

2. watch API的实现

先来看看Vue3源码中是如何实现watch API的。

packages/reactivity/src目录下,有一个叫做baseHandlers.ts的文件,其中定义了一个createGetterInvoker函数,它的作用是返回一个getter函数,这个getter函数可以直接触发依赖收集。这里我们只关注它是如何实现的:

export function createGetterInvoker(fn) {
  const invoker = (...args) => {
    return fn(...args)
  }
  ;(invoker as any).__inject__ = true // 用于标记当前函数是一个getter函数
  return invoker
}

通过以上代码可以看到,createGetterInvoker函数的作用是返回一个函数,这个函数会被标记为一个getter函数,以便在后续的代码中识别。

watch函数中我们传入了两个参数:第一个参数是要监听的对象,第二个参数是回调函数,具体实现如下:

export function watch(getter: () => any, cb: Function, options?: WatchOptions) {
  const fn = () => {
    cb(getter(), value)
  }

  const { lazy, deep, flush, onTrack, onTrigger } = options || {}
  const onInvalidate = () => {
    runner.effect.stop()
  }
  const runner = effect(
    fn,
    lazy
      ? { lazy: true, scheduler: () => {
          if (!runner.isActive) {
            runner.activate()
            fn()
          }
        } }
      : {
          scheduler: () => {
            if (!runner.isFlushPending) {
              runner.isFlushPending = true
              nextTick(runner.flush)
            }
          }
        }
  )

  if (deep) {
    traverse(getter())
  }

  let value = undefined
  if (!lazy) {
    value = getter()
    // 触发一次回调,以便获取初始的状态
    cb(value, undefined)
  }

  // 保存effect对象,以便在用户手动解绑时使用
  const effect = runner.effect
  effect.onInvalidate = onInvalidate

  ...
}

在上面的代码中,实际上是通过effect函数来进行依赖收集的。effect函数会返回一个对象,称之为effect对象,它有很多属性和方法,其中最重要的两个属性是depsdepsCount,它们用于记录这个effect对象所依赖的响应式对象以及其数量。

watch函数中,我们通过effect()函数创建了一个effect对象,然后在后续的代码中,将我们传入的回调函数作为这个effect对象fn属性来执行。

同时,我们还把getter()函数传入了traverse函数中,表示要执行一次“深遍历”操作,以便把响应式对象中的所有属性都进行依赖收集。

需要注意的是,我们在代码的开头处用到了patchFlagshapeFlag这两个变量,它们其实是跟Vue3中的虚拟DOM相关的,这里我们不用管它们是如何实现的,只需要知道它们的存在即可。

3. watch函数的用例分析

我们可以通过下面的示例来进一步了解watch函数的用例和实现细节。

// 一个简单的对象
const obj = reactive({ count: 0 })

// 操作对象的count属性
const operateObj = (num) => {
  obj.count += num
}

// 监听对象的count属性
watch(
  () => obj.count,
  (newVal, oldVal) => {
    console.log(`count由${oldVal}变为${newVal}`)
  }
)

// 改变对象的count属性
operateObj(1)
operateObj(2)

在上述代码中,我们通过reactive将一个普通的对象变成了响应式对象,然后对其count属性进行了监听。

然后我们又通过operateObj函数对count属性进行了两次修改。由于我们已经对count属性进行了监听,所以就会执行相关的回调函数,控制台会输出下面的内容:

count由0变为1
count由1变为3

这说明了watch函数的实现逻辑是正确的,并且能够很好地实现对响应式对象的监测。

总结

我们通过分析Vue3源码来了解了watch函数的实现逻辑,以及它在实际应用中的使用方法。在Vue3.x中,watch函数的重要性不言而喻,我们可以通过它来监听一个值,然后在值发生变化时执行相关的业务逻辑,从而提高Vue应用的响应性和可维护性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue3源码解析watch函数实例 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作

    使用vuex作为全局状态管理器,可以让我们更好地管理组件之间的数据共享。然而,在使用vuex时,我们也会遇到一些坑,其中最常见的就是修改vuex中的数据后,组件中的页面没有及时地渲染。以下为使用vuex时如何避免这些问题的攻略: 1. 避免直接处理vuex状态 直接修改vuex中的状态,可能会导致状态与组件的同步问题。我们应该使用mutation来修改状态。…

    Vue 2023年5月29日
    00
  • Vue select 绑定动态变量的实例讲解

    下面我将详细讲解如何在Vue中使用select绑定动态变量的实例攻略。 首先,我们需要导入Vue.js,然后创建Vue实例,并在该实例的data属性中定义我们需要绑定的动态变量(这里我们定义一个变量名为selectedValue)。然后我们需要在Vue实例中声明一个options对象,其中包含一个数组,该数组中包含我们需要绑定到select元素的选项。最后,…

    Vue 2023年5月29日
    00
  • vue.js 输入框输入值自动过滤特殊字符替换中问标点操作

    下面是“vue.js 输入框输入值自动过滤特殊字符替换中问标点操作”的完整攻略。 一、需求背景 在开发 Web 应用时,有些输入框需要对用户输入的特殊字符进行过滤和转换操作,例如将中文标点符号替换成英文标点符号。这样可以避免用户输入的字符对后续的数据处理、展示等造成影响,提高应用的稳定性和用户使用体验。 二、实现方法 1. Vue 指令实现输入框自动过滤 V…

    Vue 2023年5月27日
    00
  • mpvue 单文件页面配置详解

    我来为你详细讲解“mpvue 单文件页面配置详解”的完整攻略。 mpvue 单文件页面配置详解 1. 简介 mpvue 是一款使用 Vue.js 开发小程序的前端框架,可在小程序原生 API 基础上,结合 Vue.js 语法规范进行开发。 在 mpvue 中,我们可以通过单文件组件(SFC)的形式,实现对小程序页面的开发和配置。通过配置 SFC 的 temp…

    Vue 2023年5月27日
    00
  • Vue的混合继承详解

    Vue的混合继承详解 在Vue中,混合继承(Mixins)是一种非常常用的组件复用方式。它允许我们将多个组件共用的代码提取到一个混合对象中,然后在需要的组件中使用mixins选项进行混合。 一、基本用法 我们将要使用到一个示例,这是一个Vue组件定义的基本结构: Vue.component(‘my-component’, { mixins: [myMixin…

    Vue 2023年5月28日
    00
  • element-ui中页面缩放时table表格内容错位的解决

    为了解决element-ui中页面缩放时table表格内容错位的问题,我们可以采用以下措施: 1. CSS调整 在表格的父元素中添加CSS样式,使其在缩放时保持宽度不变: .parent { overflow: auto; white-space: nowrap; } 其中,overflow: auto表示在缩放时出现滚动条;white-space: now…

    Vue 2023年5月28日
    00
  • vue中的虚拟dom知识点总结

    下面是关于“Vue中的虚拟DOM知识点总结”的完整攻略: 什么是虚拟DOM 虚拟DOM是一种通过JS对象描述DOM树结构,实现DOM树的高效更新的技术。Vue中也是采用虚拟DOM来实现数据驱动视图的,Vue会通过模板生成虚拟DOM树,当数据发生变化时,Vue会根据新的数据生成新的虚拟DOM树,并通过Diff算法对比新旧虚拟DOM树的差异,最终最小化DOM操作…

    Vue 2023年5月28日
    00
  • 详解vue-cli 脚手架项目-package.json

    下面是详解vue-cli 脚手架项目-package.json的完整攻略。 什么是vue-cli脚手架项目-package.json 在使用Vue.js构建前端项目时,我们通常使用Vue CLI来快速创建项目的基础结构。Vue CLI通过自动生成基础代码、提供开发服务器、打包和部署等功能,减少了我们在项目搭建和管理过程中的工作量。在Vue CLI生成的项目中…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部