欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > Vue3源码学习7-PatchFlags使用位算符

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

2025/5/8 1:26:53 来源:https://blog.csdn.net/Bruce__taotao/article/details/147730427  浏览:    关键词: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('攻击中')
}

🧠 小结口诀(记忆):

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


版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词