源码学习——snabbdom(三)

1,211 阅读3分钟

前言

上节我们介绍了init过程中所涉及到的方法,着重讲解了updateChildren,整体看下来init创建、更新都离不开vonde,本节我们就来学习一下vnode的创建过程。

h函数

在snabbdom中我们可以通过h函数来创建vnode,用过vue的同学肯定对h不陌生,该函数接收三个参数:

  • sel:标签或选择器表示创建dom的类型。
  • data:可选,接收一个对象,包含dom元素数据,比如style属性。
  • children:可选,表示子节点元素,接收一个字符串或vnode数组。
// 创建一个div 展示出hello
import { h } from "snabbdom";
const vnode = h("div", { },'hello');

源码

打开h.ts文件就能找到h函数,函数的参数上面我们提到了,对应的ts类型是在vnode.ts中。

QQ图片20240803161025.png vnode的属性也不少,如果我们能够熟练掌握这些属性也就吃透了vnode。h函数也会利用这些属性去创建vnode,下面我们跟着源码来解析h函数:

image.png
注意,这里b一般代表data,c代表children。

  • 首先变量定义与参数类型的判断,这里用到了is.arrayis.primitive两个判断方法:
export const array = Array.isArray;
export function primitive(s: any): s is string | number {
return (
typeof s === "string" ||
typeof s === "number" ||
s instanceof String ||
s instanceof Number
);
}

array对应的就是Array.isArray;primitive通过typeof、instanceof判断string与numner类型。

  • data跟children都是通过不同的类型去赋值,首先判断c参数:
    数组——赋值给children变量;string、number赋值给text变量;vnode类型也赋值给children。
  • 接着判断b参数,跟c参数不一样的是最后b参数会赋值给data,就是为了兼容第二个参数未写,直接写第三个参数的情况。
    通过以上步骤我们就从参数获取到了想要的数据,继续查阅剩余代码:

image.png

  • 判断children,非空时进行循环判断,当元素为text时,用vnode创建,注意此时参数只会传text。
  • 如果标签是svg标签,就用addNS创建虚拟dom,最后将处理好的数据用vnode处理一下返回。vnode函数也很简单,就是增加了key。

QQ图片20240803173129.png
到此我们就能明白vnode就是属性的集合,我们会通过这些属性渲染出真实dom。上面还用到了addNS专门处理svg:

QQ图片20240803173446.png

  • SVG namespace (w3.org)命名空间赋值给ns。
  • 判断sel是否为foreignObject,该元素就是表示svg不用再处理;判断children元素。
  • 最后循环children,如果children包含svg进行递归处理。 整个思路很简单,就是需要我们了解一下svg相关的知识点。

fragment

在h.ts文件中处理h函数,还有fragment,该函数目前处于试验阶段,我们了解一下,函数的作用是创建一个vnode并转换成DocumentFragment

import { fragment } from "snabbdom";
const vnode = fragment(["hello"]);

QQ图片20240803181359.png
整体思路跟h函数基本一样,唯一的区别就是返回的属性要少一些,这里不再过多赘述。

总结

以上就是h函数的源码解析,通过本节相信大家对vnode会有更清晰地理解。