前言
上节我们介绍了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中。
vnode的属性也不少,如果我们能够熟练掌握这些属性也就吃透了vnode。h函数也会利用这些属性去创建vnode,下面我们跟着源码来解析h函数:
注意,这里b一般代表data,c代表children。
- 首先变量定义与参数类型的判断,这里用到了is.array、is.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,就是为了兼容第二个参数未写,直接写第三个参数的情况。
通过以上步骤我们就从参数获取到了想要的数据,继续查阅剩余代码:
- 判断children,非空时进行循环判断,当元素为text时,用vnode创建,注意此时参数只会传text。
- 如果标签是svg标签,就用addNS创建虚拟dom,最后将处理好的数据用vnode处理一下返回。vnode函数也很简单,就是增加了key。
到此我们就能明白vnode就是属性的集合,我们会通过这些属性渲染出真实dom。上面还用到了addNS专门处理svg:
- 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"]);
整体思路跟h函数基本一样,唯一的区别就是返回的属性要少一些,这里不再过多赘述。
总结
以上就是h函数的源码解析,通过本节相信大家对vnode会有更清晰地理解。