vue3原理和源码分析 - watch 源代码

news2024/11/15 19:32:55

https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/apiWatch.ts

目录

Watch

@/packages/runtime-core/src/apiWatch.ts

 watch.dot


https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/apiWatch.ts

Watch

@/packages/runtime-core/src/apiWatch.ts

watch和watchEffect都是在调用doWatch函数,所以文核心就是doWatch函数

export function watchEffect(
    effect: WatchEffect,
    options?: WatchOptionsBase
){
  return doWatch(effect, null, options)  
}
export function watchPostEffect(
    effect: WatchEffect,
    options?: DebuggerOptions
){
    options.plush = 'post'
    return doWatch(effect, null, options)  
}
export function watchSyncEffect(
    effect: WatchEffect,
    options?: DebuggerOptions
){
    options.plush = 'sync'
    return doWatch(effect, null, options)  
}
// 上面几个函数都指向doWatch()
// 对watch函数进行重载,4次
export function watch<
    T extends MultiWatchSources,
    Immediate extends Readonly<boolean> = false
>(
    sources:[...T],
    cb: WatchCallback<MapSources<T,false>,MapSources<T,Immediate>>,
    options?: WatchOptions<Immediate>
): WatchStopHandle
// ...
export function watch<
    T = any,
    Immediate extends Readonly<boolean> = false
>(
    sources: T | WatchSource<T>,
    cb: any,
    options?: WatchOptions<Immediate>
): WatchStopHandle {
    return doWatch(source as any, cb, options)
}
// 核心函数 doWatch
function doWatch(
    // source:
    // WatchSource是个ref
    // WatchEffect是个副作用
    // cb:
    // watch独有的,watchEffect时是null
    source: WatchSource | WatchSource[] | WatchEffect | object,
     cb: WatchCallback | null,
     { immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ
): WatchStopHandle {
    let getter:()=> any // 获取值
    // 会有不同的回调
    if(isRef(source)) {
        getter = () => source.value    
    } else if (isReactive(spurce)) {
        getter = () => source    
    } else if (isArray(source)) {
        getter = () => 
        source.map(s => {
            if(isRef(s)) {
                return s.value            
            } else if (isReactive(s)) {
                return traverse(s)            
            } else if (isFunction(s)) {
                // 报错
                return callWithErrorHandling(s, instance, ErrorCodes.WARCH_GETTER)            
            } else {
                __DEV__ && warnInvalidSource(s)  // 报错      
            }
        })    
    } else if (isFunction(source)) {
        if(cb) {
            // watch        
        } else {
            // watchEffect        
        } 
    }
    
    // ...
    // job是effect具体要做的事情
     const job: SchedulerJob = () => {
       if(cb) {
          // watch(source, cb)
          const newValue = effect.run() // 执行一下,拿到新的值 ,基于getter拿到的effect         
          // 一些验证条件,通过之后会执行cb
          // if...
          // 	if.... hasChanged(newValue, oldValue) // 发送变化才执行
          			callWithAsyncErrorHandling(cb, ...)
        }   
           
     }
     let scheduler: EffectScheduler
     if (flush === 'sync') {
        scheduler = job as any // 直接调用调度程序函数
     } else if (flush === 'post') {
         // 放队列里,一项一项执行
         scheduler = () => queuePostRenderEffect(job, instance && instance.suspense)
     } else {
         // default: 'pre' //也放到一个队列里
         scheduler = () => {
             if (!instance || instance.isMounted) {
                 queuePreFlushCb(job)             
             } else {
                 // 使用“pre”选项,第一次呼叫必须在
                 // 组件已安装,因此可以同步调用它。
                 job()             
             }        
         }     
     }
     // new 一个 effect;scheduler:控制执行时机,实际执行的就是scheduler
     const effect = new ReactiveEffect(getter, scheduler)

}

 watch.dot

digraph {
  watchEffect -> doWatch;
  watch -> doWatch;
  doWatch -> reactiveWrapper -> initialGet;
  activeEffect[color=green]
  reactiveWrapper -> activeEffect[dir=none]
  initialGet -> trackAll_refs_reactives
  trigger -> activeEffect -> job
}
// dot language
// graphviz

 

 

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

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

相关文章

6.3 B树,B+树

多路平衡查找树 1.定义 B树的阶&#xff1a;B树中所有结点的孩子个数的最大值&#xff0c;表示成m m阶B树&#xff1a;空树或者满足如下特性的m叉树 特性&#xff1a; 1.树中每个结点最多子树 m 关键字m-1 2.根节点不是终端结点&#xff0c;至少有两棵子树 3.根结点除外&…

基于Elasticsearch + Fluentd + Kibana(EFK)搭建日志收集管理系统

目录 1、EFK简介 2、EFK框架 2.1、Fluentd系统架构 2.2、Elasticsearch系统架构 2.3、Kibana系统架构 3、Elasticsearch接口 4、EFK在虚拟机中安装步骤 4.1、安装elasticsearch 4.2、安装kibana 4.3、安装fluentd 4.4、进入kibana创建索引 5、Fluentd配置介绍 Elas…

2023年最受欢迎和最佳WordPress主题(专家精选)

您在找2023年最佳WordPress主题吗&#xff1f; 免费和高级WordPress主题有数以千计&#xff0c;初学者很难为他们的网站选择合适的WordPress主题。 在本文中&#xff0c;我们将分享我们专家精选的2023年所有最受欢迎和最佳的WordPress主题。 本文网址: 2023年最受欢迎和最佳…

Nautilus Chain 推出全新 Layer3 DID 公民身份,限量 10 万枚免费发放

Nautilus Chain 是目前行业内首个模块化的 Layer3 机构链&#xff0c;该链此前基本完成了测试网的早期测试&#xff0c;并有望在近期上线主网。Nautilus Chain 近阶段市场活动频频&#xff0c;除了此前举办全球行活动推广 Layer3 概念外&#xff0c;其也在同期联合 Stanford Bl…

wps文档忘记保存关闭了怎么恢复

1、点击WPS左上角小箭头&#xff0c;点击下拉菜单中的工具选项&#xff0c;然后点击里面的备份中心。 2、在WPS的右侧会看到备份中心的小窗口&#xff0c;里面有自动备份的文件&#xff0c;还可以点击一键恢复即可复原之前的文件内容。 可以对之前时间段的文件打开。

什么是内存溢出,什么是内存泄漏?

文章目录 一、什么是内存溢出&#xff1f;二、什么是内存泄漏&#xff1f;三、如何避免&#xff1f; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、什么是内存溢出&#xff1f; 假设我们 JVM 中可用的内存空间只剩下 3M&#xff0c;但是我们要创…

Maven manual

Download maven Download 设置 system env… E:\apache-maven-3.9.3\bin查看版本信息 mvn -v Apache Maven 3.9.3 (21122926829f1ead511c958d89bd2f672198ae9f) Maven home: E:\apache-maven-3.9.3与Eclipse integrate Referrence&#xff0c;通常Eclipse原本就已经集成&am…

[STC32F12K54入门第三步]USART1+Modbus RTU从机

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、Modbus RTU是什么?二、Modbus RTU程序展示1.串口配置2.Timer定时器配置3.配置CRC16校验位和Modbus RTU发送函数4.主函数5.效果展示总结提示:以下是本篇文章正文内容,下面案例可供参考 一、…

WebMvcConfigurationSupport 和 WebMvcConfigurer 区别和同时使用产生的问题-解决

在Spring Boot 1.5版本都是靠重写WebMvcConfigurerAdapter的方法来添加自定义拦截器&#xff0c;消息转换器等。SpringBoot 2.0 后&#xff0c;该类被标记为Deprecated&#xff08;弃用&#xff09;。 在Spring Boot 2.0后用自己的的配置类继承WebMvcConfigurerAdapter时&…

python多维数据可视化

文章目录 数据数据可视化平行坐标RadViz雷达图Andrews曲线矩阵图相关系数热力图参考文献多维度(3维以上)数据的可视化,用常规的方法不太好实现。本文介绍几种用Python实现的将多维数据展示在二维平面中的方法。 数据 以经典的鸢尾花数据集为例。 以下是5条经过格式处理的数…

[MAUI]用纯C#代码写两个漂亮的时钟

文章目录 时钟1绘制锯齿表盘绘制指针绘制沿路径文本 时钟2绘制表盘绘制指针项目地址 谷歌在2021年5月份推出的Android 12给我们带来了新的UI设计规范Material You&#xff0c;你是否已经体验到了Material You设计的魅力了呢&#xff1f; 在原生主屏幕启动器中&#xff0c;有一个…

【杂谈理解】STM32F103引脚反转速度时间

前言 事情的起因是最近我在使用F103编写WS2812彩灯的时序时遇到了一些小问题。具体来说&#xff0c;我发现WS2812的1码的低电平部分的时序无法达到要求的220ns~380ns&#xff0c;而只能到大约580ns左右。因此&#xff0c;我开始对引脚的反转速度进行了一些测试。下面数据仅是我…

Docker一键安装个人基础开发环境-MySQL、Redis、MongoDB

Docker Compose 在个人开发环境中&#xff0c;使用 Docker Compose 可以极大地简化和优化应用程序的部署和管理过程。 Docker Compose 的配置文件通常采用 YAML 格式&#xff0c;使其易于阅读和编写。我们可以在配置文件中指定所需的容器镜像、端口映射、环境变量、数据卷挂载…

张量分解中Tucker分解和CP分解的区别与联系

CP分解图示&#xff1a; Tucker分解图示&#xff1a; 两者的区别如下&#xff1a; 主要区别&#xff1a;核张量&#xff08;core tensor&#xff09; Tucker分解的结果会形成一个核张量&#xff0c;即PCA中的主成分因子&#xff0c;来表示原张量的主要性质&#xff0c;而CP分解…

【添加anaconda环境变量】

Win11操作系统&#xff0c;首先进入到编辑环境变量界面 分别添加以下这三个&#xff0c;保存。 最后关闭pycharm,重启&#xff0c;打开Terminal&#xff0c;输入conda --version&#xff0c;成功&#xff01;

Linux删除文件夹时,报错“Error: EBUSY:resource busy or locked, unlink……”该如何解决?

目录 问题描述&#xff1a; 问题解决&#xff1a; 问题描述&#xff1a; 在linux上&#xff0c;想要删除一个文件夹&#xff0c;总是报错如下图&#xff0c;一直删除不掉。明明感觉自己并没有执行这个文件夹下的内容&#xff0c;却一直删除失败。 问题解决&#xff1a; 不得不…

如何在小程序中引入使用vant框架

一、vant框架 vantUI框架常用于移动端页面组件的基础库构建&#xff0c;为了让用户获得更趋向于原生的体验&#xff0c;它是一种相当不错的方案选择。 关于这个框架&#xff0c;它不仅有适用于移动端vue脚手架的版本&#xff0c;同时还存在可以兼容小程序开发的webapp版本。在…

业务逻辑一定要紧密执行,希望大家引以为戒!——记一次惨痛的教训【伸手党福利】【又是贷款上班的一天】

切记一定要先执行业务逻辑再进行其他操作&#xff01; 程序员的教训 问题现象 后台传来报警&#xff0c;充值平台余额不足&#xff0c;发现大量充值记录。 分析 先看一下代码&#xff1a; 发起http的post请求&#xff0c;然后将返回体显示&#xff0c;并用logs记入日志&a…

STM32F4_nRF24L01无线通讯

目录 前言&#xff1a; 1. nRF24L01无线模块简介 2. nRF24L01状态机 3. nRF24L01模式 4. nRF24L01的SPI配置 4.1 nRF24L01 Rx 和 Tx 的初始化配置 4.2 nRF24L01相关寄存器 5. 硬件连接 6. 实验程序 6.1 main.c 6.2 NRF24L01.c 6.3 NRF24L01.h 前言&#xff1a; S…

10-切片是什么?【视频版】

目录 问题视频解答 问题 视频解答 点击观看&#xff1a; 10-切片是什么&#xff1f;