VDOM 、 diff、JSX
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),不可用的,优化后才能用,即:
- 只比较统计,不跨级比较;
- tag 不相同,直接删除重建,不再进行深度比较;
- tag(selector)两者都相同,则相同,不再进行深度比较;
优化后时间复杂度变为可用的O(n)。
diff算法流程
pathcVnode
- vnode.text === undefined,vnode.children 一般都有值;
- 对比新旧节点,都有 children,进行两个 children 之间的对比;
- 新 children 有,旧 children 没有,则添加 新children,清空旧的 text;
- 旧 children 有值,新 children 没值,移除 旧 children,添加新 text;
- 旧 text 有值,新的 text 没值,移除 旧 text;
updateChildren 进行 key 的对比
- 开始 vs 开始
- 结束 vs 结束
- 开始 vs 结束
- 结束 vs 开始
- 当前新节点 与每个旧节点进行对比
- 找到key 相同,则 判断 tag 是否相同
新增、移除 vnode
- 新增 :addVnodes()
- 移除: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?
- VDOM diff 算法会根据 key 判断是都要删除元素
- 匹配到 key,判断 tag 是否相同,直接移动即可,性能好;
- 未匹配到,则直接删除重建;
附上本人用脚画的草图:
VDOM 、 diff、JSX相关推荐
- Docker常用命令、超实用、讲解清晰明了(rm、stop、start、kill、logs、diff、top、cp、restart ...)
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 查看docker信息(version.info) # 查看docker版本 $docker v ...
- linux meld 中文乱码,linux下paste、diff、meld的使用
linux下paste.diff.meld的使用 非常实用的几个小命令,可用于对文件.目录进行处理. paste 逐行合并两个文件 -d 指定两个文件合并后每行之间的分隔符,如: -d " ...
- linux下paste、diff、meld的使用
linux下paste.diff.meld的使用 非常实用的几个小命令,可用于对文件.目录进行处理. paste 逐行合并两个文件 -d 指定两个文件合并后每行之间的分隔符,如: -d " ...
- 3.14-19 wc、iconv、dos2unix、diff、vimdiff、rev
3.14 wc:统计文件的行数.单词数或字节数 wc命令用于统计文件的行数.单词数或字节数. -c 统计字节数 -w 统计单词数 -l 统计行数 -L 打印最长行的长度 -m 统计字符数 查看 ...
- 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 ...
- Git最佳实践(init、config、status、add、commit、diff、push) 1.0v
Git最佳实践 工程设计领域中使用版本控制来管理工程蓝图的设计过程,在IT开发过程中借鉴了版本控制思想管理代码的版本迭代. Git是一个开源的分布式版本控制系统,最初由Linus Torvalds创作 ...
- 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 #查看正在运行的终端上的正在运行的所有 ...
- Git log、diff、config 进阶
前一段时间分享了一篇<更好的 git log>简要介绍怎么美化 git log 命令,其中提到了 alias命令,今天再继续谈谈 git相关, 看看如何通过配置自己的 git config ...
- Git(6)-- 记录每次更新到仓库图文版(git clone、status、add、diff、commit、rm、mv命令详解)
文章目录 1.克隆现有仓库:`git clone` 2.检查当前文件状态 :`git status` 3.跟踪新文件:`git add` 4.暂存已修改的文件:`git add` 5.状态简览: `g ...
最新文章
- clientdataset 遍历字段_TClientDataSet[5]: 读取数据
- eclipse中显示jquery或extjs自动提示
- 2021年4月12日-民航上海医院-瑞金医院古北分院-检查报告单
- Manacher算法学习笔记 | LeetCode#5
- 6张图为你分析Kafka Producer 消息缓存模型
- oracle 无效数字 0,oracle to_namber之后报ora-01722:无效数字
- VAssistX 脚本
- WinCC V7.4 入门笔记
- 苹果手机密码锁如何解锁
- 7.15周三晚8点,dotnet课堂全新起航,张善友/陈计节/刘腾飞我们一起来聊聊abp的故事...
- 8086汇编基础 8080,8088,8086,80286,80386的地址线,数据线宽度
- 阿里平头哥CPU技术生态负责人陈炜:平头哥的发展之路
- Python人脸识别 Python3.7+OpenCV+Dlib+罗技C920摄像头 实现离线实时摄像头画面人脸检测+识别
- 申请免费代码签名证书
- php病人叫号的源码,diy uan4 医院叫号系统页面,用在 排队 ,各大 ,人数很多, 很长 WEB(ASP,PHP,...) 238万源代码下载- www.pudn.com...
- 《 指数基金投资指南 》by 银行螺丝钉 - 笔记 - 1、2章
- 全网征集对六如偈的理解:一切有为法,如梦幻泡影,如露亦如电,应作如是观
- C语言:L1-070 吃火锅 (15 分)
- 提高企业竞争力,如何开展知识管理工作?
- html星空炫彩粒子,炫彩粒子模拟
热门文章
- weiphp 安装( 解决 -1:fail to get xml content 问题)
- PPT提示“发现内容有问题”的解决方案
- C#: double转int , String转int
- 科目二练车 注意事项
- Springboot校园在线打印预约系统小程序【纯干货分享,附源码91740】
- 阿里云国际站注册下单流程
- Java基于springboot开发的疫苗预约小程序
- Problem F: 乌鸦坐飞机
- 严格冷启动问题的再次尝试AGNN及代码
- 企业省钱之道:是使用IDC的二手服务器还是云主机?