VDOM 、 diff、JSX

13 篇文章 0 订阅
9 篇文章 0 订阅

VDOM

为什么使用 VDOM?
  • react 和 vue:数据驱动视图
  • 直接操作 dom 非常消耗性能;
  • 计算次数减少比较困难,转移为 JS计算;
  • VDOM:使用 JS 模拟 DOM 结构,计算出最小变量,操作 DOM;
  • VDOM 是目前最合适「数据驱动视图」的技术方案;
用 JS 模拟 DOM 结构
<div className={style.container}  id="div1">
        <p>拙慕</p>
        <ul style={{fontSize:20}}>
          <li>li</li>
        </ul>
   </div>

对应的模拟出来

{
  tag: 'div',
    props: {
    className: 'container',
    id: 'div1'
  }
  children: [
    {
      tag: 'p',
      childred: '拙慕' 
    },
    {
      tag: 'ul'
      props: {
        style: 'font-size:20',
      },
      children: [{
        tag: 'li',
        children: 'lili'
      }]
    }
  ]
}
通过 snabbdom 学习 VDOM
核心内容: 以 VDOM(VNODE)描述真实DOM
  • h()创建节点
  • init设置模块,生成patch函数
  • patch对比dom差异,将差异更新的到dom中

官方文档:https://github.com/snabbdom/snabbdom
中文文档:https://github.com/coconilu/Blog/issues/152

h 函数

用法:h(<标签>,<属性>,[子元素])

var h = require('snabbdom/h').default;
var vnode = h('div', {style: {color: '#000'}}, [
  h('h1', 'Headline'),
  h('p', 'A paragraph'),
]);

转换为DOM:

<div style={{ color: '#000' }}>
        <h1>Headline</h1>
        <p>A paragraph</p>
 </div>
patch函数

用法:path(oldNode,newNode);
patch:即补丁函数。snabbdom的核心函数,可以理解为对新旧dom进行差异化的函数,判断 key 和 selector(tag) 都相等,则判断为相同元素,会返回一个新的虚拟节点。

// key :undefined
undefined ===  undefined // true
总结
  • 用 JS 模拟 DOM结构(VNODE);
  • 新旧 VNODE 对比,得出最小的更新范围,最后更新 VDOM;
  • 数据驱动视图模式下,有效控制 DOM 操作

diff

关于 diff

diff 一种对比算法,一种广泛的概念,不是 react ,vue 独有的;

在这里插入图片描述

tree diff 算法的时间复杂度是 O(n^3),不可用的,优化后才能用,即:

  1. 只比较统计,不跨级比较;
  2. tag 不相同,直接删除重建,不再进行深度比较;
  3. tag(selector)两者都相同,则相同,不再进行深度比较;

优化后时间复杂度变为可用的O(n)。

diff算法流程
pathcVnode
  1. vnode.text === undefined,vnode.children 一般都有值;
  2. 对比新旧节点,都有 children,进行两个 children 之间的对比;
  3. 新 children 有,旧 children 没有,则添加 新children,清空旧的 text;
  4. 旧 children 有值,新 children 没值,移除 旧 children,添加新 text;
  5. 旧 text 有值,新的 text 没值,移除 旧 text;
updateChildren 进行 key 的对比
  1. 开始 vs 开始
  2. 结束 vs 结束
  3. 开始 vs 结束
  4. 结束 vs 开始
  5. 当前新节点 与每个旧节点进行对比
  6. 找到key 相同,则 判断 tag 是否相同
新增、移除 vnode
  1. 新增 :addVnodes()
  2. 移除:removeVnodes()
    上述步骤只有在前一步都没命中才会继续执行下一步;

JSX 本质

通过 bable 在线编辑器查看:babeljs.cn

v16.x及以前版本

在这里插入图片描述

h 函数即 React.createElement()

v17.x及之后

在这里插入图片描述
h 函数即 jsx(),注意这里为了避免重名使用:_jsx();

总结
  • React v16.x 及以前 babel 进行 jsx 解析编译的是根据加粗样式 @babel/babel-preset-react-app 解析成React.createElement进行包裹;
  • React v17.x 及之后的版本,对 jsx 转换用react/jsx-runtime,而不再依赖React.createElement;
  • 无论是 React.createElement 还是 react/jsx-runtime,都是一个 h函数,第一个参数可以是 组件,也可以是 html tag。

React 和 Vue 循环中为什么强调使用 key?

  1. VDOM diff 算法会根据 key 判断是都要删除元素
  2. 匹配到 key,判断 tag 是否相同,直接移动即可,性能好;
  3. 未匹配到,则直接删除重建;

附上本人用脚画的草图:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值