更新dom节点,最小力度去跟新

index.html
<body>
<h1>你好啊!</h1>
<button id="btn">该变数据</button>
<div id="container"></div>
</body>
<script src="xuni/bundle.js"></script>
</html> index.js文件
import {
init,
classModule,
propsModule,
styleModule,
eventListenersModule,
h,
} from "snabbdom"; let myVnode1 = h('ul', {}, [
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1) // 改变数据
let myVnode2 = h('ul', {}, [
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
h('li', {}, '性别'), ])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
}

发现的现象

当我手动去更改页面中的数据的时候。
在点击按钮。我们发现只追加了性别。
我更改的数据并没有跟新。
说明diff是进行最小力度去跟新的

那我们把数据添加在最前面会发生什么呢?

let myVnode1 = h('ul', {}, [
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1) // 改变数据
let myVnode2 = h('ul', {}, [
//在最前面添加,发现跟刚才的比一样了?
//他将我们更改的数据复原了?
//这个时候又小伙伴会说,diff不是最小粒度去更新了
h('li', {}, '性别'),
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
}

diff不是最小粒度跟新?

在最前面添加,发现跟刚才的比一样了?
他将我们更改的数据复原了?
这个时候又小伙伴会说,diff不是最小粒度去更新了?
其实diff一直都是最小力度跟新,是你忘记增加key值了。
我们加上key值看看呢??

添加key值后

let myVnode1 = h('ul', {}, [
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1) // 改变数据
let myVnode2 = h('ul', {}, [
h('li', {key:'00x'}, '性别'),
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
}

添加key值顶级节点类型改变的情况

当我们添加key值后,发现数据果然是最小力度去更新的,对吧!
如果将ul更改为div,还是最小力度跟新吗? let myVnode1 = h('ul', {}, [
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1) // 改变数据
let myVnode2 = h('div', {}, [
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
} 这个时候我们增加上key值了,按照之前的操作。
发现一个问题。数据全部恢复最初始值了。 在采取diff算法比较:新旧节点进行比较,
比较只会在同层级进行, 不会跨层级比较。 如果两个节点都是一样的,那么就深入检查他们的子节点。
果两个节点不一样那就说明 Vnode 完全被改变了(ul和div节点不一样),
就可以直接使用新节点替换老节点。【他们的子代不会进行比较了】 虽然这两个节点不一样但是他们的子节点一样怎么办?
别忘了,diff可是逐层比较的,
如果[第一层不一样那么就不会继续深入比较第二层了。
(我在想这算是一个缺点吗?相同子节点不能重复利用了??...) 这个时候你可能会说:这个diff算法也不会那么牛逼呢!
并不是最优的。
【虽然这两个节点不一样但是他们的子节点一样怎么办?】
在我们工作中:其实这指一种非常合理的机制。
我们几乎并不会出现这样的情况
<ul v-if="falg">
<li v-for="item,index" in list>{{item }}</li>
</ul> <ol v-if="falg">
<li v-for="item,index" in list>{{item }}</li>
</ol>
这样的代码在我们工作中几乎是不会出现的呢? 什么叫做不会跨层比较?
<div>
<p>123123 </p>
</div>

<div>
<h2> <p>123123 </p> </h2>
</div> div与div比较
p与h2比较
当p与h2比较的时候,他们他们节点不一样,直接使用替换。
此时并不会在使用diff了

diff算法是如何比较的,保证让你看的明明白白的!的更多相关文章

  1. ReactiveNative学习之Diff算法

    React 源码剖析系列 - 不可思议的 react diff深入浅出React(四):虚拟DOM Diff算法解析React diff 算法总结链接引用的文章React出于性能的考虑,为了避免频繁操 ...

  2. Vue源码终笔-VNode更新与diff算法初探

    写完这个就差不多了,准备干新项目了. 确实挺不擅长写东西,感觉都是罗列代码写点注释的感觉,这篇就简单阐述一下数据变动时DOM是如何更新的,主要讲解下其中的diff算法. 先来个正常的html模板: & ...

  3. 浅析vue2.0的diff算法

    一.前言 如果不了解virtual dom,要理解diff的过程是比较困难的. 虚拟dom对应的是真实dom, 使用document.CreateElement 和 document.CreateTe ...

  4. 深入理解react中的虚拟DOM、diff算法

    文章结构: React中的虚拟DOM是什么? 虚拟DOM的简单实现(diff算法) 虚拟DOM的内部工作原理 React中的虚拟DOM与Vue中的虚拟DOM比较 React中的虚拟DOM是什么?   ...

  5. react中虚拟dom的diff算法

    .state 数据 .jsx模板 .生成虚拟dom(虚拟DOM就是一个js对象,用它来描述真实DOM) ['div', {id:'abc'}, ['span', {}, 'hello world']] ...

  6. react性能调谐与diff算法

    一个页面其实就相当于是一颗dom树,里面有很多它的子节点,然后你每次去操作一个事件,它都会生成一个虚拟dom,它会跟上一个虚拟dom进行比对,这里运用的算法叫做diff算法,当它找到需要改变的组件的时 ...

  7. 【Vuejs】351- 带你解析vue2.0的diff算法

    前言 vue2.0加入了virtual dom,有向react靠拢的意思.vue的diff位于patch.js文件中,该算法来源于snabbdom,复杂度为O(n).了解diff过程可以让我们更高效的 ...

  8. 直接操作DOM一定比虚拟DOM操作耗时,diff算法,key值,虚拟 DOM的定义

    直接操作DOM一定比虚拟DOM操作耗时吗? 或者一次直接DOM操作一定比一次虚拟DOM操作耗时吗? 1)虚拟DOM的本质就是一个JS对象,虚拟DOM减少了真实DOM的操作,当修改数据的时候,就是修改虚 ...

  9. React中diff算法的理解

    React中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DO ...

  10. diff算法深入一下?

    文章转自豆皮范儿-diff算法深入一下 一.前言 有同学问:能否详细说一下 diff 算法. 简单说:diff 算法是一种优化手段,将前后两个模块进行差异化比较,修补(更新)差异的过程叫做 patch ...

随机推荐

  1. 一通百通,带你一次性全理解Spring 中的Template

    摘要:Template定义了问题的边界,子类定义了具体的实现,只要在模板的范围内玩耍就可以了. 本文分享自华为云社区<Spring 中的Template一次全理解,解析问题的本质>,作者: ...

  2. Mac Maven环境变量配置 zsh: command not found: mvn

    之前配过环境变量,但是后来打开还是报 zsh: command not found: mvn 需要在运行前先刷下环境变量 source ~/.bash_profile 每次使用前都刷一下比较麻烦,这是 ...

  3. WPF 对Border 边框进行投影

    画一个 Border 对边框进行投影 <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.micr ...

  4. 获取标准报表CJI3的ALV数据

    1.CJI3 运行标准程序CJI3,获取对象和业务货币值,在其他程序中展示 2.代码展示 CJI3对应程序名rkpep003,最终展示的ALV结构可以再程序中找到. 因为本实例只获取其中两个字段的值, ...

  5. 我让 ChatGPT 化身为全知全能的文档小助理,啥姿势她都会......

    ChatGPT 虽然只是一个对话型人工智能,但已经震惊了全世界,有人甚至认为人工智能的奇点已经到来.未来一定会有很多人失业,从工业革命开始,每出现一次重大的技术变革,就必然会有一批人失业,我们要直面现 ...

  6. php开发之文件读取、写入

    前言 续之前的系列,这里php开发的文件操作的内容读取以及文本写入的部分 文件读取代码的实现 css代码 本系列的php博客都是这个css,名字都是index.css /* css样式初始化 */ * ...

  7. python之logging日志

    一.logging介绍: 使用 logging.debug(text)来打印信息,info等的使用方法与debug一致,都只有一个位置参数 默认日志界别为:会输出warning以上的信息,代码示例: ...

  8. spring boot 整合kafka

    本文为博主原创,未经允许不得转载: 1. 引入spring boot kafka依赖 <dependency> <groupId>org.springframework.kaf ...

  9. 基于taro搭建小程序多项目框架

    前言 为什么需要这样一个框架,以及这个框架带来的好处是什么? 从字面意思上理解:该框架可以用来同时管理多个小程序,并且可以抽离公用组件或业务逻辑供各个小程序使用.当你工作中面临这种同时维护多个小程序的 ...

  10. 一个容易弄错的.textContent和text()问题

    最近在写一些前端页面,遇到需要通过点击事件获取被点击对象的文本内容,正确代码如下: <!DOCTYPE html> <html lang="en"> < ...