【Vue源码】图解 diff算法 与 虚拟DOM-snabbdom-最小量更新原理解析-手写源码-updateChildren

文章目录

来自尚硅谷的课程笔记 课程链接 尚硅谷邵山欢(考拉老师)Vue之虚拟DOM和diff算法
加入大量的注释以及大量改写,新增很多插图解释diff算法
第八章仔细说明了老师说的一些比较含糊的地方
源码链接 https://gitee.com/ykang2020/vue_learn

0. 文章结构预览

在这里插入图片描述

0.1 虚拟DOM如何被渲染函数(h函数)产生

目标:手写h函数

0.2 diff算法的原理

目标:手写diff算法

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

1. 介绍

1.1 diff算法

精细化比较
在这里插入图片描述

1.2 虚拟DOM

本课程不涉及DOM如何变成虚拟DOM
这属于模板编译原理范畴
但是虚拟节点变成DOM节点在diff中可以做到
在这里插入图片描述

1.3 关系——diff是发生在虚拟DOM上的

新虚拟DOM和旧虚拟DOM进行diff(精细化比较),算出应该如何最小量更新,最后反映到真正的DOM上

在这里插入图片描述

2. snabbdom 简介 及 准备工作

2.1 简介

snabbdom(瑞典语,“速度”)是著名的虚拟DOM库,是diff算法的鼻祖
Vue源码借鉴了snabbdom
源码使用TypeScript写的https://github.com/snabbdom/snabbdom
从npm下载的是build出来的JavaScript版本

npm install -D snabbdom

2.2 搭建初始环境

1. 安装snabbdom

cnpm install -S snabbdom

在这里插入图片描述

2. 安装webpack5并配置

cnpm i -D webpack@5 webpack-cli@3 webpack-dev-server@3

配置webpack5

module.exports = {
   
  // webpack5 不用配置mode
  // 入口
  entry: "./src/index.js",
  // 出口
  output: {
   
    // 虚拟打包路径,文件夹不会真正生成,而是在8080端口虚拟生成
    publicPath: "xuni",
    // 打包出来的文件名
    filename: "bundle.js",
  },
  // 配置webpack-dev-server
  devServer: {
   
    // 静态根目录
    contentBase: 'www',
    // 端口号
    port: 8080,
  },
};

3. 复制官方demo Example

src/index.js

import {
   
  init,
  classModule,
  propsModule,
  styleModule,
  eventListenersModule,
  h,
} from "snabbdom";

const patch = init([
  // Init patch function with chosen modules
  classModule, // makes it easy to toggle classes
  propsModule, // for setting properties on DOM elements
  styleModule, // handles styling on elements with support for animations
  eventListenersModule, // attaches event listeners
]);

const container = document.getElementById("container");

const vnode = h("div#container.two.classes", {
    on: {
    click: function () {
    } } }, [
  h("span", {
    style: {
    fontWeight: "bold" } }, "This is bold"),
  " and this is just normal text",
  h("a", {
    props: {
    href: "/foo" } }, "I'll take you places!"),
]);
// Patch into empty DOM element – this modifies the DOM as a side effect
patch(container, vnode);

const newVnode = h(
  "div#container.two.classes",
  {
    on: {
    click: function () {
    } } },
  [
    h(
      "span",
      {
    style: {
    fontWeight: "normal", fontStyle: "italic" } },
      "This is now italic type"
    ),
    " and this is still just normal text",
    h("a", {
    props: {
    href: "/bar" } }, "I'll take you places!"),
  ]
);
// Second `patch` invocation
patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new state

在这里插入图片描述

3. h函数的介绍与使用

3.1 介绍

用来产生虚拟节点(vnode)
在这里插入图片描述
虚拟节点vnode的属性

{
   
	children: undefined// 子元素 数组
	data: {
   } // 属性、样式、key
	elm: undefined // 对应的真正的dom节点(对象),undefined表示节点还没有上dom树
	key: // 唯一标识
	sel: "" // 选择器
	text: "" // 文本内容
}

3.2 使用h函数 创建虚拟节点

// 创建虚拟节点
var myVnode1 = h('a', {
    props: {
    href: 'https://www.baidu.com' } }, 'YK菌')
console.log(myVnode1)

在这里插入图片描述

3.3 使用patch函数 将虚拟节点上DOM树

// 创建patch函数
const patch = init([
  classModule,
  propsModule,
  styleModule,
  eventListenersModule,
]);

// 创建虚拟节点
var myVnode1 = h(
  "a",
  {
    props: {
    href: "https://www.baidu.com", target: "_blank" } },
  "YK菌"
);

// 让虚拟节点上树
let container = document.getElementById("container");
patch(container, myVnode1);

在这里插入图片描述

3.4 h函数嵌套使用,得到虚拟DOM树(重要)

在这里插入图片描述

const myVnode3 = h('ul', [
  h('li', '苹果'),
  h('li', '香蕉'),
  h('li', '西瓜'),
  h('li', '番茄'),
])

// 让虚拟节点上树
let container = document.getElementById("container");
patch(container, myVnode3);

在这里插入图片描述

const myVnode3 = h('ul', [
  h('li', '苹果'),
  h('li', [
    h('div', [
      h('p', '香蕉'),
      h('p', '草莓')
    ])
  ]),
  h('li', h('span','西瓜')),
  h('li', '番茄'),
])
<
  • 43
    点赞
  • 137
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
Vue和React都是流行的前端框架,它们在实现上有很多相似之处,但也有很多不同之处。其中,最明显的区别就是在处理视图更新时采用的不同的数据绑定方式和不同的虚拟DOM实现。 Diff算法Vue采用的是双向绑定机制,即当数据发生变化时,Vue会自动更新视图,这是通过Object.defineProperty()实现的。Vue更新机制是基于依赖追踪的。当数据发生变化时,Vue会重新渲染视图,并使用Diff算法来计算哪些元素需要更新Diff算法的核心是比较新旧虚拟DOM树的差异。 React采用的是单向数据流机制,即当数据发生变化时,React不会直接更新视图。相反,React会创建一个新的虚拟DOM树,然后使用Diff算法比较新旧虚拟DOM树的差异,并且只更新发生变化的节点。React中的Diff算法被称为Reconciliation算法,它是基于两个假设:1.相同类型的组件会生成相似的树形结构;2.不同类型的组件会生成不同的树形结构。 虚拟DOMVue虚拟DOM是轻级的,只包含必要的信息,比如标签名、属性和子节点等。Vue中的虚拟DOM是通过render()函数生成的,它是一个JavaScript对象。当数据发生变化时,Vue会重新生成一个新的虚拟DOM树,并使用Diff算法比较新旧虚拟DOM树的差异。Vue中的虚拟DOM只关注视图和数据之间的关系,而不关注其他方面,比如事件处理等。 React的虚拟DOM也是一个JavaScript对象,但它比Vue虚拟DOM更加完整和复杂。React的虚拟DOM包含完整的组件层级信息、组件状态和事件处理等。当数据发生变化时,React会重新生成一个新的虚拟DOM树,并使用Diff算法比较新旧虚拟DOM树的差异。与Vue不同,React的虚拟DOM不仅关注视图和数据之间的关系,还关注其他方面,比如事件处理等。 总的来说,Vue和React在Diff算法虚拟DOM的实现上有所不同。Vue采用的是双向绑定机制,它的虚拟DOM只关注视图和数据之间的关系;React采用的是单向数据流机制,它的虚拟DOM包含完整的组件层级信息、组件状态和事件处理等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值