⚡ 30 秒速记

  • h 生成描述,挂载与更新由渲染器完成
  • 首次从容器生成节点,后续比较新旧虚拟节点
  • 更新后保存新的描述,作为下次比较基准
  • 列表身份、属性与文本分别处理
  • 渲染库的具体接口不能泛化成统一标准

虚拟节点描述想要的界面,渲染器负责把这份描述落实到页面。 以提供 h 和 patch 的库为例,先创建节点描述,首次交给容器完成挂载;数据变化后再把旧描述和新描述交给更新函数。完成后要保存新的树,作为下一次基准。这样把业务状态与节点操作分开,但不同库的参数形式和内部比较方式并不完全相同。

版本校准: 原理文章中的代码代表特定实现与写作时间。应用到当前项目时,应先确认浏览器、框架或工具的主版本,再区分稳定的规范语义、可变化的内部实现和项目自身约束。

# 一、什么是 vdom

  • 用 JS 模拟 DOM 结构
  • DOM 变化的对比,放在 JS 层来做
  • 提高重绘性能

# 二、设计一个需求场景

img

用jQuery实现

img img img

遇到的问题

  • DOM 操作是“昂贵”的,js 运行效率高
  • 尽量减少 DOM 操作,而不是“推倒重来”
  • 项目越复杂,影响就越严重
  • vdom 即可解决这个问题

img

# 三、vdom 的如何应用,核心 API 是什么

什么是 vdom

img

介绍 snabbdom

img img

介绍 snabbdom - h 函数

img

介绍 snabbdom - patch 函数

img

重做jQuery的demo

  • 使用 data生成 vnode
  • 第一次渲染,将 vnode 渲染到 #container中
  • 并将 vnode 缓存下来
  • 修改 data 之后,用新 data 生成 newVnode
  • 将 vnode 和 newVnode 对比

img

核心 API

  • h(‘<标签名>’, {…属性…}, […子元素…])
  • h(‘<标签名>’, {…属性…}, ‘….’)
  • patch(container, vnode)
  • patch(vnode, newVnode)

# 四、介绍一下 diff 算法

# 4.1 vdom 为何使用 diff 算法

  • DOM 操作是“昂贵”的,因此尽量减少 DOM 操作
  • 找出本次 DOM 必须更新的节点来更新,其他的不更新
  • 这个“找出”的过程,就需要 diff 算法

img

patch(container, vnode)

img img

演示过程

img img img img

# 4.2 diff 实现过程

  • patch(container, vnode) 和 patch(vnode, newVnode)
  • createElment
  • updateChildren

💬 面试官追问

  • 调用 h 后页面没变化,是哪里漏了?

    h 通常只创建描述,并不操作真实节点。还要把结果交给渲染器的挂载或更新入口。

  • 每次都拿最初那棵树比较,会出问题吗?

    可能让描述与真实页面脱节。更新完成后保存新树,下次以最近一次结果为基准,才能正确计算后续变化。

  • 列表项只改文字,为什么不必重建整张表?

    身份和类型匹配时,可以复用节点并修改目标文本。具体省掉多少工作,取决于比较和宿主更新实现。

  • 节点操作集中起来,就不会触发布局了吗?

    仍可能触发,只是更容易控制时机和范围。避免中间强制读取布局,并用浏览器记录确认实际成本。

webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
点击侧边栏下一篇
折叠侧边栏
收起全部