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. 未匹配到,则直接删除重建;

附上本人用脚画的草图:

VDOM 、 diff、JSX相关推荐

  1. Docker常用命令、超实用、讲解清晰明了(rm、stop、start、kill、logs、diff、top、cp、restart ...)

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 查看docker信息(version.info) # 查看docker版本 $docker v ...

  2. linux meld 中文乱码,linux下paste、diff、meld的使用

    linux下paste.diff.meld的使用 非常实用的几个小命令,可用于对文件.目录进行处理. paste 逐行合并两个文件 -d 指定两个文件合并后每行之间的分隔符,如: -d " ...

  3. linux下paste、diff、meld的使用

    linux下paste.diff.meld的使用 非常实用的几个小命令,可用于对文件.目录进行处理. paste 逐行合并两个文件 -d 指定两个文件合并后每行之间的分隔符,如: -d " ...

  4. 3.14-19 wc、iconv、dos2unix、diff、vimdiff、rev

    3.14 wc:统计文件的行数.单词数或字节数 wc命令用于统计文件的行数.单词数或字节数. -c 统计字节数 -w 统计单词数 -l 统计行数     -L 打印最长行的长度 -m 统计字符数 查看 ...

  5. linux基础命令与文件系统(ip a、ls、cat、vim、cd、pwd、hostname、date、reboot、poweroff、echo、touch、rm、mkdir、diff、file)

    目录 一.Linux命令提示符 二.linux基础命令 1.ip a命令 2.ls 命令 3.cat 查看文件命令 4.vim编辑命令 5.cd 命令 6.pwd 命令 7.hostname 命令 8 ...

  6. Git最佳实践(init、config、status、add、commit、diff、push) 1.0v

    Git最佳实践 工程设计领域中使用版本控制来管理工程蓝图的设计过程,在IT开发过程中借鉴了版本控制思想管理代码的版本迭代. Git是一个开源的分布式版本控制系统,最初由Linus Torvalds创作 ...

  7. linux基础命令3(ps、top、ulimit、mkdir、more、cat、diff、grep、touch、cp、find、rm、split、mv、)

    (待修改) 一.基础命令 1.ps  ps -A  #所有的进程均显示出来  ps -e  #此参数的效果和指定"A"参数相同 ps -a  #查看正在运行的终端上的正在运行的所有 ...

  8. Git log、diff、config 进阶

    前一段时间分享了一篇<更好的 git log>简要介绍怎么美化 git log 命令,其中提到了 alias命令,今天再继续谈谈 git相关, 看看如何通过配置自己的 git config ...

  9. Git(6)-- 记录每次更新到仓库图文版(git clone、status、add、diff、commit、rm、mv命令详解)

    文章目录 1.克隆现有仓库:`git clone` 2.检查当前文件状态 :`git status` 3.跟踪新文件:`git add` 4.暂存已修改的文件:`git add` 5.状态简览: `g ...

最新文章

  1. clientdataset 遍历字段_TClientDataSet[5]: 读取数据
  2. eclipse中显示jquery或extjs自动提示
  3. 2021年4月12日-民航上海医院-瑞金医院古北分院-检查报告单
  4. Manacher算法学习笔记 | LeetCode#5
  5. 6张图为你分析Kafka Producer 消息缓存模型
  6. oracle 无效数字 0,oracle to_namber之后报ora-01722:无效数字
  7. VAssistX 脚本
  8. WinCC V7.4 入门笔记
  9. 苹果手机密码锁如何解锁
  10. 7.15周三晚8点,dotnet课堂全新起航,张善友/陈计节/刘腾飞我们一起来聊聊abp的故事...
  11. 8086汇编基础 8080,8088,8086,80286,80386的地址线,数据线宽度
  12. 阿里平头哥CPU技术生态负责人陈炜:平头哥的发展之路
  13. Python人脸识别 Python3.7+OpenCV+Dlib+罗技C920摄像头 实现离线实时摄像头画面人脸检测+识别
  14. 申请免费代码签名证书
  15. php病人叫号的源码,diy uan4 医院叫号系统页面,用在 排队 ,各大 ,人数很多, 很长 WEB(ASP,PHP,...) 238万源代码下载- www.pudn.com...
  16. 《 指数基金投资指南 》by 银行螺丝钉 - 笔记 - 1、2章
  17. 全网征集对六如偈的理解:一切有为法,如梦幻泡影,如露亦如电,应作如是观
  18. C语言:L1-070 吃火锅 (15 分)
  19. 提高企业竞争力,如何开展知识管理工作?
  20. html星空炫彩粒子,炫彩粒子模拟

热门文章

  1. weiphp 安装( 解决 -1:fail to get xml content 问题)
  2. PPT提示“发现内容有问题”的解决方案
  3. C#: double转int , String转int
  4. 科目二练车 注意事项
  5. Springboot校园在线打印预约系统小程序【纯干货分享,附源码91740】
  6. 阿里云国际站注册下单流程
  7. Java基于springboot开发的疫苗预约小程序
  8. Problem F: 乌鸦坐飞机
  9. 严格冷启动问题的再次尝试AGNN及代码
  10. 企业省钱之道:是使用IDC的二手服务器还是云主机?