虚拟dom及diff算法之 —— h函数和diff函数

编程入门 行业动态 更新时间:2024-10-24 13:30:46

虚拟dom及diff算法之 —— h<a href=https://www.elefans.com/category/jswz/34/1771370.html style=函数和diff函数"/>

虚拟dom及diff算法之 —— h函数和diff函数

新虚拟dom和老虚拟dom进行diff算法(精细化比较),算出如何最小量更新,最后反映到真实dom上

diff是发生在虚拟dom上的

模板编译

虚拟dom如何产生 - 渲染函数(h函数)

h函数产生虚拟节点(vnode)

Dom节点:<a href="">真实Dom</a>
调用h函数:h('a',{props:{href:""}},'真实Dom')
生成虚拟节点:{"sel":"a","data":{props:{href=""}},"text:"真实Dom"}

虚拟节点有哪些属性

{children:{}, // 子元素data:{}, // 属性,样式elm:undefined, // 这个元素真正的dom节点,如果是undefined证明这个虚拟dom还没有上树key:undefined, // 节点唯一标识sel:"div", // 选择器text:"真实Dom" // 文字
}

使用patch函数让虚拟节点上树,一个容器只能让一个虚拟dom上树,除非h函数进行嵌套

import { init, classModule, propsModule, styleModule, eventListenersModule, h } from 'snabbdom'
// 创建patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
// 创建虚拟节点
var myVnode1 = h('a', { props: { href: '', target: '_blank' } }, '真实Dom')
// 使用patch函数让虚拟节点上树
const container = document.getElementById('container')
// 一个容器只能让一个虚拟dom上树,除非h函数进行嵌套
patch(container, myVnode2)

h函数可以嵌套使用创建虚拟dom树

var myVnode3 = h('ul', {}, [h('li', '苹果'), h('li', '西瓜'), h('li', '香蕉'), h('li', '火龙果')])

第二个参数写不写不影响

var myVnode21 = h('div', {}, '我是一个盒子')
var myVnode22 = h('div', '我是一个盒子')

第三个参数如果再有一个子元素可以不要数组,如果有多个子元素需要使用数组

var myVnode3 = h('ul', {}, [h('li', {}, '苹果'),h('li', '西瓜'),h('li', [h('div', [h('p', '嘻嘻'), h('p', '哈哈')])]),h('li', h('span', '榴莲'))
])

h函数的重载(h函数的实现形式)

h('div')
h('div','文字'),
h('div',[])
h('div',h())
h('div',{},'文字'),
h('div',{},[])
h('div',{},h())

vnode函数

// 函数目的:将5个参数组合成一个对象返回
export default function (sel, data, children, text, elm) {return { sel, data, children, text, elm }
}

h函数的实现

import vnode from './vnode'
// 弱重载:函数重载功能没有实现,必须接收3个参数
// 形态1:h('div',{},'文字')
// 形态2:h('div',{},[])
// 形态3:h('div',{},h())
export default function (sel, data, c) {// 检查参数个数if (arguments.length !== 3) throw new Error('低配版,必须传入3个参数')// 检查参数c的类型if (typeof c === 'string' || typeof c === 'number') {// 形态1的h函数:文字return vnode(sel, data, undefined, c, undefined)} else if (Array.isArray(c)) {// 形态2的h函数:数组let children = []// 遍历c,收集childrenfor (let i = 0; i < c.length; i++) {// c[i]必须是一个有sel属性的对象if (!(typeof c[i] === 'object' && c[i].hasOwnProperty('sel'))) throw new Error('传入的数组有项不是h函数')// 不用执行c[i],因为在调用h函数的时候已经执行了children.push(c[i])}// 循环结束,锁门children收集完毕了,可以返回带有children属性的虚拟节点了return vnode(sel, data, children, undefined, undefined)} else if (typeof c === 'object' && c.hasOwnProperty('sel')) {// 形态3的h函数:h函数(一个有sel属性的对象),即的唯一的childrenlet children = [c]return vnode(sel, data, children, undefined, undefined)} else {throw new Error('传入的第三个参数不对')}
}

diff算法原理

最小量更新:key很重要,key是这个节点的唯一标识,告诉diff算法,在更改前后他们是同一个dom节点

只有是同一个虚拟dom节点,才能进行精细化比较,否则会暴力删除旧的,插入新的
如果定义是同一个虚拟节点:选择器和key都相同

只进行同层比较,不会进行跨层比较,而是暴力删除旧的,插入新的

diff不是那么无微不至,但是2,3在实际的vue开发中,基本不会遇见

创建节点时,所有子节点都是需要递归创建的

手写第一次上树时

虚拟dom如何通过diff变成真正的dom

更多推荐

虚拟dom及diff算法之 —— h函数和diff函数

本文发布于:2023-11-16 17:33:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1630011.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   算法   dom   diff

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!