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

这篇具有很好参考价值的文章主要介绍了虚拟dom及diff算法之 —— h函数和diff函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

新虚拟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('传入的第三个参数不对')
  }
}

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

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

diff算法原理

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

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

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

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

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

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

patch函数的实现文章来源地址https://www.toymoban.com/news/detail-742049.html

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

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

到了这里,关于虚拟dom及diff算法之 —— h函数和diff函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue 虚拟DOM

    在当今Web开发领域中,构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架,正是为了满足这些需求而诞生。它采用了MVVM架构模式,并通过数据驱动和组件化的方式,使我们能够更轻松地构建出优雅而高效的Web应用程序。

    2024年02月22日
    浏览(39)
  • vue的虚拟DOM

    虚拟DOM就是一个JS对象,用它来描述真实DOM demo1: 多次执行dom操作 demo2: 只执行一次dom操作 比较运行时间:得到结论 越多的真实dom操作,越损耗性能 操作数据要大大的减少性能损耗,提高渲染效率 第一种更新DOM的方案 第二种更新DOM的方案 第三种使用虚拟DOM的方案 key是虚拟

    2024年02月09日
    浏览(40)
  • Vue面试之虚拟DOM

        最近在整理一些前端面试中经常被问到的问题,分为vue相关、react相关、js相关、react相关等等专题,可持续关注后续内容,会不断进行整理~     虚拟 DOM 是用 JavaScript 对象来模拟实际 DOM 结构的一种抽象表示。它描述了组件的结构、属性和事件等信息,但与实际的页面

    2024年01月21日
    浏览(39)
  • vue中的虚拟dom

    DOM操作是Web开发中非常昂贵和低效的操作,尤其是在用户界面频繁更新的情况下。此时,在每次数据更新时重新渲染整个DOM树会导致应用程序性能下降。 为了解决这个问题,虚拟DOM被引入到前端开发中。虚拟DOM把整个DOM树抽象成一个JS对象,这样开发者就可以直接操作JS对象

    2024年02月09日
    浏览(41)
  • 【vue】diff 算法详解

    diff算法是一种通过 同层的树节点 进行比较的高效算法         diff算法的目的就是找出新旧不同虚拟DOM之间的差异,使最小化的更新视图,所以 diff 算法本质上就是比较两个js对象的差异 特点         1. 比较只会在同层级进行,不会跨层级比较         2. 在diff比较的构成

    2024年02月02日
    浏览(34)
  • vue 虚拟DOM的优劣说明

    Vue.js 使用虚拟 DOM(Virtual DOM)来提高应用的性能。虚拟 DOM 是一种编程概念,它通过在内存中创建一个与真实 DOM 结构相同的虚拟结构,来优化对真实 DOM 的操作。下面是对 Vue.js 中虚拟 DOM 的优劣说明和代码示例。 优势: 性能优化 :Vue.js 通过虚拟 DOM 减少了直接操作真实

    2024年01月25日
    浏览(33)
  • 什么是 VUE的虚拟 DOM?

    虚拟 DOM(Virtual DOM)是一个在内存中以 JavaScript 对象的形式表示的轻量级的 DOM 抽象层。当页面的状态发生改变时,Vue 3 会生成新的虚拟 DOM,并通过与上一次生成的虚拟 DOM 进行比较,找出实际发生了变化的部分。然后,Vue 3 仅对这些变化的部分进行实际 DOM 操作,而不是对整

    2024年02月14日
    浏览(44)
  • vue的diff算法原理

    vue基于虚拟DOM做更新,diff的核心就是比较两个虚拟节点的差异。 vue的diff算法是 平级比较 ,不考虑跨级比较的情况。内部采用 深度递归 + 双指针 的方式进行比较 先比较是否是相同节点 key tag (标识,标签名) 相同节点比较属性,并复用老节点(将老的虚拟dom复用给新的虚拟

    2023年04月25日
    浏览(35)
  • vue diff 双端比较算法

    使用四个变量 oldStartIdx、oldEndIdx、newStartIdx 以及 newEndIdx 分别存储旧 children 和新 children 的两个端点的位置索引 除了位置索引之外,还需要拿到四个位置索引所指向的 VNode 使用旧 children 的头一个 VNode 与新 children 的头一个 VNode 比对,即 oldStartVNode 和 newStartVNode 比较对。 使用

    2024年02月14日
    浏览(42)
  • vue源码阅读之什么是虚拟dom

    前面简单说过数据响应式原理,大体是个怎么流程,数据发生变化,我们界面如何更新。 依赖收集收集的是watcher,然后当数据发生变化的时候dep通知watcher,然后watcher负责updateComponent。 那么更新组件过程中,有个很重要的概念叫做虚拟dom。 所谓虚拟dom,就是用一个js对象来

    2024年02月13日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包