h函数为什么叫h?

1,668 阅读3分钟

看 vue 源码的时候,提到了snabbdom,而这个库里有个很重要的函数h

我就好奇了,为啥用hh是什么的缩写,表示的到底是什么?

然后就翻到hyperScript这个词,然后找到了解释

Create HyperText with JavaScript, on client or server

htmlHyperText Markup Language的缩写,超文本标记语言,本质是文本,但用的是特殊的标记语言写的,其可以表示 纯文本和媒体资源、表单等其他的非文本,所以是超文本。

那么hyperScript其实是用 js 创建超文本,这里的超文本特指HTML,而 JS 里可以用DOM(document object model)表示HTML,但 js 本身是有DOM API的,为什么作者还要写这个库?

举个例子就明白了:

创建这样的结构:

<div class="parent">
  <span class="son">颜酱真酷</span>
</div>

传统的方式:

function createDiv() {
  const span = document.createElement("span");
  span.className = "son";
  const div = document.createElement("div");
  div.className = "parent";
  div.appendChild(span);
  return div;
}

显然这还是结构简单,属性少的情况,如果很多的话,非常繁琐,而且可读性差。

于是想到了,用简单的语句描述,想要的 DOM 结构,然后用函数统一生成想要的结构

其实一个元素的三斧头:标签名、标签的其他自身信息、子元素

function hyperScript(tagName, attrs, children) {
  // ....
}
const h = hyperScript;
// 这样执行这个方法就可以生成上面的div了
h("div", { className: "parent" }, h("span", { className: "son" }, "颜酱真酷"));

这样可读性强很多,所以这个库的,h函数,是用节点的描述(标签名、属性和事件、子元素)去创建真实节点的,并返回这个真实节点。

snabbdom这个库是处理vnode的,所以它的的h函数,是用节点的描述(标签名、标签的其他自身信息、子元素)创建虚拟节点的,并返回这个虚拟节点。

于是平时看到h 函数的时候,心里的联想是Create Virtual HyperText with JavaScript

大白话,h函数就是用节点的描述(标签名、标签的其他自身信息、子元素)创建虚拟节点。

为什么有了 h 函数还要 vnode 函数?

其实 h 函数,更多的时候,是便于用户传参,用户只需要考虑三个要素:标签名、标签的其他自身信息、子元素。

但是一个vnode有 6 种属性,其中的 key 是从 data 来的,所以vnode函数需要 5 个参数,用户调用的话,显然增加理解门槛,所以用h函数简化了传参,降低调用门槛,而h函数内部调用vnode函数生成vnode

vnode2 vnode3

h函数的参数最多三个,但只有第一个是必传项,第二个参数和第三个都是可传项,所以内部对各种情况作了判断,已生成正确的vnode

// npm i snabbdom 可以快速在编辑器控制台看下,h三个参数,必填的是第一个,data始终是对象,children可以是数组也可以是字符串
const { h } = require("snabbdom");

console.log(h("div.only-sel"));
console.log(h("div.only-data", { name: "demo" }));
console.log(h("div.only-text", "qqq"));
console.log(
  h("div.only-text", { key: "data这里设置key" }, [h("span"), "子text"])
);

vnode4

引用