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

news/2024/7/10 0:36:49 标签: vue, diff, 虚拟dom, h函数

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

diff是发生在虚拟dom上的

模板编译

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

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

Dom节点:<a href="https://www.baidu.com">真实Dom</a>
调用h函数h('a',{props:{href:"https://www.baidu.com"}},'真实Dom')
生成虚拟节点:{"sel":"a","data":{props:{href="https://www.baidu.com"}},"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: 'https://www.baidu.com', 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,收集children
    for (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属性的对象),即的唯一的children
    let children = [c]
    return vnode(sel, data, children, undefined, undefined)
  } else {
    throw new Error('传入的第三个参数不对')
  }
}

请添加图片描述

请添加图片描述

diff_117">diff算法原理

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

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

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

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

请添加图片描述

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

patch函数的实现

// init主要是组装函数模型的
const patch = init([classModule, propsModule, styleModule, eventListenersModule])

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


http://www.niftyadmin.cn/n/5153555.html

相关文章

翻页电子杂志制作功略,快收藏,保管好用!

翻页电子杂志&#xff0c;我相信这对大家很熟悉吧&#xff0c;大家也都经常看电子杂志吧。它和我们的生活紧密相关&#xff0c;也极大地改变了我们的阅读方式。听到这“翻页电子杂志”&#xff0c;是不是觉得制作起来肯定很难很复杂&#xff0c;需要专业的人才能制作呢&#xf…

Android Studio(对话框Alert)

前言 前面介绍了常用控件的相关属性&#xff0c;那些控件的使用起来也很容易。在本节及后面的章节介绍的控件将是相比于前面使用起来较为复杂的&#xff08;不过使用多了&#xff0c;也很容易上手&#xff09;。 这些控件常常需要配合java代码来使用&#xff0c;比如说对话框、…

[MICROSAR Adaptive] --- Hello Adaptive World

Automotive E/E Architecture and AUTOSAR Adaptive Platform Vector Solution: MICROSAR Adaptive First project: Hello Adaptive World Summary 1 引言 1.1 AP诞生的历史背景 新一代电子电器架构通常将车内的节点分为三类。计算平台,预控制器和传感器执行器相关的节点,…

【Redis】分布式锁

分布式锁 分布式锁是一种在分布式系统中实现同步机制的技术。它允许多个进程或节点在访问共享资源时进行同步&#xff0c;以确保它们按照预期的顺序执行。 这篇文章使用Redis来分布式锁&#xff0c;通俗的来说&#xff0c;分布式锁本质上要实现的目标就是在Redis里面占一个 “…

connect-history-api-fallback原理

connect-history-api-fallback是一个用于处理前端路由的中间件&#xff0c;它的原理是在服务器接收到请求时&#xff0c;检查请求的路径是否匹配到静态文件&#xff08;如HTML、CSS、JS等&#xff09;&#xff0c;如果不匹配&#xff0c;则将请求重定向到前端的入口文件&#x…

HMAC是什么?有什么作用? 安当加密

HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写&#xff0c;它是一种基于Hash函数和密钥进行消息认证的方法&#xff0c;由H.Krawezyk&#xff0c;M.Bellare&#xff0c;R.Canetti于1996年提出&#xff0c;并于1997年作为RFC2104被公布&am…

Javascript知识点详解:数组、Array 对象

目录 数组 定义 数组的本质 对象有两种读取成员的方法&#xff1a; length 属性 in 运算符 for...in 循环和数组的遍历 数组的空位 类似数组的对象 Array 构造函数 静态方法 Array.isArray() 实例方法 valueOf()&#xff0c;toString() push()&#xff0c;pop(…

C生万物 | 从浅入深理解指针【第三部分】(qsort的使用和模拟实现)

C生万物 | 从浅入深理解指针【第四部分】&#xff08;qsort的使用和模拟实现&#xff09; 文章目录 C生万物 | 从浅入深理解指针【第四部分】&#xff08;qsort的使用和模拟实现&#xff09;回调函数是什么&#xff1f;qsort使用举例qsort函数的模拟实现 回调函数是什么&#x…