Vue3源码学习7-PatchFlags使用位算符

文章目录

  • 前言
    • ✅ 一、基础知识:什么是二进制?
    • ✅ 二、位运算的基本操作
    • ✅ 三、左移运算 `<<`
    • ✅ 四、实际用途:如何用于状态标记(PatchFlags)
    • ✅ 五、组合多个状态标记
    • ✅ 六、小结口诀(记忆)
    • ✅ 一、语法含义
    • ✅ 二、在 `PatchFlags` 中的作用
      • 示例说明:
    • ✅ 三、这样写的好处
      • 1. **便于使用位运算组合多个标记**
      • 2. **检查时快速**
      • 3. **性能极高**
    • ✅ 四、实际示例
    • ✅ 五、小结一句话(适合面试)
  • 补充
    • ✅ 1. **权限管理(权限位)**
    • ✅ 2. **日志级别控制(Logging Flags)**
    • ✅ 3. **状态管理(多个状态叠加)**
    • ✅ 4. **DOM 元素样式/行为控制**
    • ✅ 5. **游戏开发中的状态控制**
    • 🧠 小结口诀(记忆):


前言

vue3在编译相关的源码中:有这一段

export enum PatchFlags {/*** Indicates an element with dynamic textContent (children fast path)*/TEXT = 1,/*** Indicates an element with dynamic class binding.*/CLASS = 1 << 1,/*** Indicates an element with dynamic style* The compiler pre-compiles static string styles into static objects* + detects and hoists inline static objects* e.g. style="color: red" and :style="{ color: 'red' }" both get hoisted* as:* 
js* const style = { color: 'red' }* render() { return e('div', { style }) }**/STYLE = 1 << 2,
// 省略其他

这样用有什么好处?我们先从最基本的二进制和位运算概念讲起,再理解 1 << n 的用法,最后回到 PatchFlags


✅ 一、基础知识:什么是二进制?

计算机底层只认识 0 和 1,我们用“二进制”来表示:

十进制二进制
10001
20010
40100
81000

✅ 二、位运算的基本操作

运算符含义示例(十进制)示例(二进制)结果
&按位与5 & 30101 & 0011 = 00011
``按位或5 | 30101 | 0011 = 01117
<<左移1 << 20001 → 01004
>>右移4 >> 10100 → 00102

✅ 三、左移运算 <<

左移就是把二进制整体向左“推”一位,后面补 0。

1      => 二进制是 0001
1 << 1 =>0010 => 十进制 2
1 << 2 =>0100 => 十进制 4
1 << 3 =>1000 => 十进制 8

所以可以理解成:

1 << n === 2 的 n 次方

✅ 四、实际用途:如何用于状态标记(PatchFlags)

Vue 3 中通过这个方式给每种类型的“变更”分配唯一标志位:

export enum PatchFlags {TEXT = 1,         // 0001 => 1CLASS = 1 << 1,   // 0010 => 2STYLE = 1 << 2,   // 0100 => 4PROPS = 1 << 3,   // 1000 => 8
}

每个标志只占一位,组合时不会冲突。


✅ 五、组合多个状态标记

// 组合标记
const patchFlag = PatchFlags.CLASS | PatchFlags.STYLE // 2 | 4 = 6 => 0110// 检查是否包含 PatchFlags.STYLE
if (patchFlag & PatchFlags.STYLE) {console.log('需要更新 style')
}

因为:

patchFlag = 0110
STYLE     = 0100
&         = 0100 → 非 0,说明包含

✅ 六、小结口诀(记忆)

技术点口诀
1 << n就是 2 的 n 次方,用来生成唯一的二进制标志位
`` 或运算多个标志合并为一个 patchFlag
& 与运算判断某个标志是否存在于 patchFlag 中(非 0 表示存在)

在这里插入图片描述

这是 TypeScript(或 JavaScript)中的位运算符 <<,表示左移位运算(left shift)


✅ 一、语法含义

1 << 1  // 结果是 2
1 << 2  // 结果是 4
1 << 3  // 结果是 8

换句话说:

1 << n === 2

✅ 二、在 PatchFlags 中的作用

Vue 3 的编译器使用 PatchFlags 来标记 虚拟 DOM 节点有哪些动态变化的部分

示例说明:

export enum PatchFlags {TEXT = 1,         // 0001CLASS = 1 << 1,   // 0010 => 2STYLE = 1 << 2,   // 0100 => 4PROPS = 1 << 3,   // 1000 => 8// 依此类推...
}

✅ 三、这样写的好处

1. 便于使用位运算组合多个标记

  • 可以用按位或(|)组合多个 patch 标志:

    const patchFlag = PatchFlags.TEXT | PatchFlags.CLASS
    // 即 0001 | 0010 = 0011 => patchFlag = 3
    

2. 检查时快速

  • Vue 更新虚拟 DOM 时可以通过按位与(&)检查:

    if (patchFlag & PatchFlags.CLASS) {// 有 CLASS 需要处理
    }
    

3. 性能极高

  • 位运算是底层最轻量的运算方式之一,比数组查找或对象比较快很多
  • 避免使用多个 boolean 类型判断。

✅ 四、实际示例

const patchFlag = PatchFlags.CLASS | PatchFlags.STYLE; // 2 | 4 = 6if (patchFlag & PatchFlags.CLASS) {console.log('需要更新 class')
}if (patchFlag & PatchFlags.STYLE) {console.log('需要更新 style')
}

✅ 五、小结一句话(适合面试)

Vue 3 使用位移表达式(如 1 << n)生成 2 的幂,实现 PatchFlags 的唯一性标识、位掩码组合、按位判断等优化逻辑,在虚拟 DOM diff 过程中既高效又灵活。


补充

非常好!这种“位运算 + 标志位”的方式是一种经典的性能优化技巧,不仅用于 Vue 的 PatchFlags,还广泛应用于许多实际场景中,比如权限控制、状态管理、日志等级控制等。

下面我列出几个常见 应用场景 并配上示例说明:


✅ 1. 权限管理(权限位)

场景:一个用户可能拥有多个权限,如读、写、删、改等。

// 权限定义(每个权限占一位)
export enum Permission {READ  = 1 << 0,  // 0001 = 1WRITE = 1 << 1,  // 0010 = 2DELETE = 1 << 2, // 0100 = 4UPDATE = 1 << 3  // 1000 = 8
}// 设置权限(读 + 写)
let userPermission = Permission.READ | Permission.WRITE  // 0011 = 3// 检查是否有写权限
if (userPermission & Permission.WRITE) {console.log('有写权限')
}

优点:节省空间(用一个整数存多个权限),判断权限快(位运算)。


✅ 2. 日志级别控制(Logging Flags)

enum LogLevel {ERROR = 1 << 0,WARN  = 1 << 1,INFO  = 1 << 2,DEBUG = 1 << 3
}// 当前启用的日志级别(错误 + 警告)
const activeLogLevel = LogLevel.ERROR | LogLevel.WARNfunction log(msg: string, level: LogLevel) {if (activeLogLevel & level) {console.log(`[${LogLevel[level]}]`, msg)}
}log('Something wrong', LogLevel.ERROR) // 会输出
log('Just info', LogLevel.INFO)        // 不会输出

✅ 3. 状态管理(多个状态叠加)

场景:表示一个任务的多个状态(如:初始化、加载中、完成、失败)

enum TaskStatus {INIT     = 1 << 0,LOADING  = 1 << 1,SUCCESS  = 1 << 2,FAILED   = 1 << 3
}let currentStatus = TaskStatus.INIT | TaskStatus.LOADING// 判断是否正在加载
if (currentStatus & TaskStatus.LOADING) {console.log('任务加载中')
}

✅ 4. DOM 元素样式/行为控制

例如用于判断是否启用多个 UI 特效:

enum UIFlags {HIGHLIGHT = 1 << 0,BLINK     = 1 << 1,SHADOW    = 1 << 2
}let elementFlags = UIFlags.HIGHLIGHT | UIFlags.SHADOWif (elementFlags & UIFlags.HIGHLIGHT) {// 给元素加高亮
}

✅ 5. 游戏开发中的状态控制

例如角色可能处于多种状态:跳跃、攻击、被击中等。

enum PlayerState {IDLE    = 1 << 0,JUMPING = 1 << 1,ATTACK  = 1 << 2,HURT    = 1 << 3
}let currentState = PlayerState.JUMPING | PlayerState.ATTACK// 检查是否正在攻击
if (currentState & PlayerState.ATTACK) {console.log('攻击中')
}

🧠 小结口诀(记忆):

“一个数,多个状态;左移位,值唯一;按位或,组合用;按位与,判断快。”


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

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

相关文章

在 Vue 2 中使用 qrcode 库生成二维码

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

电子电器架构 --- 网关释放buffer的必要性

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…

Java中Stream、File、方法递归

文章目录 十五、Stream流、File、方法递归1、Stream1.1 什么是Stream1.2 获取Stream流1.3 Stream流常见的中间方法1.3 Stream流常见的终结方法1.4 收集Stream流 2、File、IO流&#xff08;一&#xff09;2.1 存储数据的方案2.2 File&#xff1a;代表文本2.3 常用方法一&#xf…

挑战用豆包教我学Java01天

今天是豆包教我学Java的第一天&#xff0c;废话不多说直接开始。 1.每日题目&#xff1a; 基础语法与数据类型 题目&#xff1a;编写一个 Java 程序&#xff0c;从控制台读取两个整数&#xff0c;然后计算它们的和、差、积、商&#xff0c;并输出结果。题目&#xff1a;编写…

文章记单词 | 第67篇(六级)

一&#xff0c;单词释义 cylinder&#xff1a;英 [ˈsɪlɪndə(r)] 美 [ˈsɪlɪndər] &#xff0c;名词&#xff0c;意为 “圆筒&#xff1b;圆柱体&#xff1b;汽缸&#xff1b;&#xff08;有特定用途的&#xff09;圆筒形物品”。fool&#xff1a;英 [fuːl] 美 [fuːl]…

Make:独立创造者手册——从0到1的商业自由之路

目录 如何获得创业想法 • 解决你自己的问题 • 从微观细分市场起步 • 从问题出发&#xff0c;而非解决方案 • 记录与验证想法 如何构建产品 • 快速构建最小化产品 • 对抗完美主义 • 自行开发 vs. 外包 • 学习基础编程的必要性 案例与洞见 • Levelsio的70个项目与5%成…

spark基本介绍

一、Spark概述 Spark是一种基于内存的快速、通用、可拓展的大数据分析计算引擎。 Hadoop是一个分布式系统结构的基础架构。 二、Spark与Hadoop相比较的优势&#xff1a; 1. 处理速度&#xff1a;Hadoop&#xff1a;数据处理速度相对较慢 Spark&#xff1a;速度比Hadoop快很…

Pdf转Word案例(java)

Pdf转Word案例&#xff08;java&#xff09; 需要导入aspose-pdf.jar 需要先手动下载jar包到本地&#xff0c;然后通过systemPath在pom文件中引入。 下载地址&#xff1a;https://releases.aspose.com/java/repo/com/aspose/aspose-pdf/25.4/ <dependency><groupId&…

探索 C++ 语言标准演进:从 C++23 到 C++26 的飞跃

引言 C 作为一门历史悠久且广泛应用的编程语言&#xff0c;其每一次标准的演进都备受开发者关注。从早期的 C98 到如今的 C23&#xff0c;再到令人期待的 C26&#xff0c;每一个版本都为开发者带来了新的特性和改进&#xff0c;推动着软件开发的不断进步。本文将深入探讨 C23 …

如何有效防御服务器DDoS攻击

分布式拒绝服务&#xff08;DDoS&#xff09;攻击通过大量恶意流量淹没服务器资源&#xff0c;导致服务瘫痪。本文将提供一套结合代码实现的主动防御方案&#xff0c;涵盖流量监控、自动化拦截和基础设施优化。 1. 实时流量监控与告警 目标&#xff1a;检测异常流量并触发告警…

【Bootstrap V4系列】学习入门教程之 组件-折叠(Collapse)

Bootstrap V4系列 学习入门教程之 组件-折叠&#xff08;Collapse&#xff09; 折叠&#xff08;Collapse&#xff09;How it works一、Example二、Horizontal 水平的三、Multiple targets 多个目标四、Accordion example 手风琴示例 折叠&#xff08;Collapse&#xff09; 通…

C24-数组

数组的引入:方便对同一类型的数据进行管理(一个班级里的45个同学、一个篮子里的12个苹果)数组的定义: 数据类型 数组名[常量表达式(也就是元素的个数)];int a[10]; //这里定义了一个能存放10个元素的整形数组数组初始化 完全初始化 int arr[3]{5,6,8};部分初始化 int arr[10]{…

手持小风扇方案解说---【其利天下技术】

春去夏来&#xff0c;酷暑时节&#xff0c;小风扇成为外出必备的解暑工具&#xff0c;近年来&#xff0c;随着无刷电机的成本急剧下降&#xff0c;小风扇也逐步从有刷变无刷化了。 数量最大的如一箱无刷马达&#xff0c;其次三相低压无刷电机也大量被一些中高端风扇大量采用。…

C++函数栈帧详解

函数栈帧的创建和销毁 在不同的编译器下&#xff0c;函数调用过程中栈帧的创建是略有差异的&#xff0c;具体取决于编译器的实现&#xff01; 且需要注意的是&#xff0c;越高级的编译器越不容易观察到函数栈帧的内部的实现&#xff1b; 关于函数栈帧的维护这里我们要重点介…

CPU-GPU-NPU-TPU 概念

1.CPU 中央处理器&#xff08;Central Processing Unit&#xff0c;简称CPU&#xff09;作为计算机系统的运算和控制核心&#xff0c;是信息处理、程序运行的最终执行单元。CPU自产生以来&#xff0c;在逻辑结构、运行效率以及功能外延上取得了巨大发展。 2.GPU GPU&#xff0…

Java学习手册:ORM 框架性能优化

一、优化实体类设计 减少实体类属性 &#xff1a;仅保留必要的字段&#xff0c;避免持久化过多数据。例如&#xff0c;对于一个用户实体类&#xff0c;如果某些信息&#xff08;如详细地址&#xff09;不是经常使用&#xff0c;可以将其拆分到单独的实体类中。使用合适的数据类…

XMP-Toolkit-SDK 编译与示例程序

一、前言 最近在调研图片的元数据读写方案&#xff0c;需要了解 XMP 空间以及如何在 XMP 空间中读写元数据&#xff0c;本文做一个相关内容的记录。 XMP-Toolkit-SDK 以及 XMP标准简介 XMP-Toolkit-SDK 是 Adobe 提供的一套开源软件开发工具包&#xff08;SDK&#xff09;&a…

计算机硬件(南桥):主板芯片组FCH和PCH的区别

在计算机主板设计中&#xff0c;FCH&#xff08;Fusion Controller Hub&#xff09;和PCH&#xff08;Platform Controller Hub&#xff09;分别是AMD和Intel对主板芯片组中“南桥”&#xff08;Southbridge&#xff09;部分的命名。尽管两者功能相似&#xff0c;但受不同厂商架…

数据库系统概论-基础理论

数据库系统概述&#xff1a; 1、记录&#xff1a;计算机中表示和存储数据的一种格式或方法。 2、数据库&#xff08;DataBase, DB&#xff09;&#xff1a;数据库是长期储存在计算机内、有组织、可共享的大量数据集合。可为各种用户共享。 3、数据库管理系统&#xff08;Dat…

在 R 中,清除包含 NA(缺失值)的数据

在 R 中&#xff0c;清除包含 NA&#xff08;缺失值&#xff09;的数据可以通过多种方式实现&#xff0c;具体取决于你希望如何处理这些缺失值。以下是几种常见的方法&#xff0c;包括删除包含 NA 的行、删除包含 NA 的列&#xff0c;或者用特定值填充 NA。 1. 删除包含 NA 的…