前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • React专栏

    • React组合式开发实战

      • 前端开发的四个时代
      • 企业管理系统的前世今生
      • 可视化页面搭建工具
      • 实战篇 01:开发前准备
      • 实战篇 02:项目脚手架
      • 实战篇 03:页面布局方案
      • 实战篇 04:权限管理机制
      • 实战篇 05:菜单匹配逻辑
      • 实战篇 06:消息通知设计
      • 实战篇 07:多语言支持
      • 继往开来:可视化页面搭建工具
    • React Hooks与Immutable实战

    • React SSR服务端渲染与同构实践

    • IM聊天系统前端开发实践

    • 微前端开发实战

    • React进阶实践

  • Vue专栏

  • 移动端专栏

  • Node专栏

  • 前端工程化专栏

  • 算法专栏

  • Typescript专栏

  • 其他专栏

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

# 前言

在开启本篇章之前,我们先来思考一个问题,假设有以下模板:

html
复制代码<template>
  <p>hello world</p>
  <p>{{ msg }}</p>
</template>>
@前端进阶之旅: 代码已经复制到剪贴板

其中一个 p 标签的节点是一个静态的节点,第二个 p 标签的节点是一个动态的节点,如果当 msg 的值发生了变化,那么理论上肉眼可见最优的更新方案应该是只做第二个动态节点的 diff,而无需进行第一个 p 标签节点的 diff。

如果熟悉 Vue 2.x 的小伙伴可能会知道,在 Vue 2.x 版本中在编译过程中有一个叫做 optimize 的阶段,会进行标记静态根节点的操作,被标记为静态根节点的节点,一方面会生成一个 staticRenderFns,首次渲染会以这个静态根节点 vnode 进行缓存,后续渲染会直接取缓存中的,从而避免重复渲染;另一方面生成的 vnode 会带有 isStatic = true 的属性,将会在 diff 过程中被跳过。但 Vue 2.x 对静态节点进行缓存就是一种空间换时间的优化策略,为了避免过度优化,在 Vue 2.x 中,识别静态根节点是需要满足:

  1. 子节点是静态节点;
  2. 子节点不是只有一个静态文本节点的节点。

所以,上面的示例第一个 p 标签在 Vue 2.x 中不会被判定位静态根节点,也就无法进行优化。

关于 Vue 2.x 如何做的编译时优化,这里只是简单进行了介绍,想了解更多的小伙伴可以参考这里: 入口开始,解读 Vue2 源码(七)—— $mount 内部实现 — compile optimize标记节点。

那么 Vue 3 呢?还是和 Vue 2 一样吗?答案显然是否定的,首先我们前面介绍了对于静态的节点,Vue 3 首先会进行静态提升,也就是相当于缓存了静态节点的 vnode,那 diff 过程呢?会跳过吗?本小节我们来一探究竟。

# PatchFlags

# 是什么?

首先,我们需要认识一个 PatchFlags 这个属性,它是一个枚举类型,里面是一些二进制操作的值,用来标记在节点的 patch 类型。具体的枚举内容如下:

export const enum PatchFlags {
  // 动态文本的元素
  TEXT = 1,

  // 动态 class 的元素
  CLASS = 1 << 1,

  // 动态 style 的元素
  STYLE = 1 << 2,

  // 动态 props 的元素
  PROPS = 1 << 3,

  // 动态 props 和有 key 值绑定的元素
  FULL_PROPS = 1 << 4,

  // 有事件绑定的元素
  HYDRATE_EVENTS = 1 << 5,

  // children 顺序确定的 fragment
  STABLE_FRAGMENT = 1 << 6,

  // children 中有带有 key 的节点的 fragment
  KEYED_FRAGMENT = 1 << 7,

  // 没有 key 的 children 
fe
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • React专栏

    • React组合式开发实战

      • 前端开发的四个时代
      • 企业管理系统的前世今生
      • 可视化页面搭建工具
      • 实战篇 01:开发前准备
      • 实战篇 02:项目脚手架
      • 实战篇 03:页面布局方案
      • 实战篇 04:权限管理机制
      • 实战篇 05:菜单匹配逻辑
      • 实战篇 06:消息通知设计
      • 实战篇 07:多语言支持
      • 继往开来:可视化页面搭建工具
    • React Hooks与Immutable实战

    • React SSR服务端渲染与同构实践

    • IM聊天系统前端开发实践

    • 微前端开发实战

    • React进阶实践

  • Vue专栏

  • 移动端专栏

  • Node专栏

  • 前端工程化专栏

  • 算法专栏

  • Typescript专栏

  • 其他专栏