Hyperscript——React 的隐藏语言

2025-06-05

Hyperscript——React 的隐藏语言

JSX 是起点

React 使用 JSX 来简化开发者的工作。所以当你写类似这样的代码时。

<div id="foo">
  Hello!
</div>
Enter fullscreen mode Exit fullscreen mode

带有反应预设的 Babel 将其转换为此。

React.createElement("div", {
  id: "foo"
}, "Hello!");
Enter fullscreen mode Exit fullscreen mode

看看Babel REPL中的这个例子。
React.createElement这是一个创建虚拟节点的函数。
这是一个众所周知的事实,你可能已经知道了。那么它的意义何在呢?

Preact 方式

如果您以前使用过 Preact,您可能会注意到它的源代码中有一个不明显的导出。

export {
        createElement,
        createElement as h,
} from './create-element';
Enter fullscreen mode Exit fullscreen mode

为了更清楚地说明,createElementPreact 中的函数与 满足相同的需求React.createElement。那么问题是,为什么它也被导出为h呢?

原因很简单。它被导出为 ,h因为它是一个 hypescript 函数
那么 hypescript 到底是什么呢?

Hyperscript 是关键

Hypescript 是一种用 JavaScript 创建超文本的语言,由 Dominic Tarr 于 2012 年创立。他的灵感来源于markaby,一种用纯 Ruby 编写 HTML 的“简短代码”。Markaby
可​​以实现类似的功能。

require 'markaby'

mab = Markaby::Builder.new
mab.html do
  head { title "Boats.com" }
  body do
    h1 "Boats.com has great deals"
    ul do
      li "$49 for a canoe"
      li "$39 for a raft"
      li "$29 for a huge boot that floats and can fit 5 people"
    end
  end
end
puts mab.to_s
Enter fullscreen mode Exit fullscreen mode

h函数允许做本质上相同的事情,但使用不同的语法。

h = require("hyperscript")

h("div#foo", "Hello!")
Enter fullscreen mode Exit fullscreen mode

它还支持嵌套和 CSS 属性。

h = require("hyperscript")

h("div#foo", 
  h("h1", "Hello from H1!", { style: { 'color': 'coral' } })
)
Enter fullscreen mode Exit fullscreen mode

查看交互式演示来了解其工作原理。

亲自动手

现在,我们知道了该h函数的作用以及为什么需要它,我们就可以编写自己的版本了。完整的示例可以在codesanbox上找到。

首先,让我们编写一个render函数,从虚拟节点创建真实的 DOM 元素。

const render = ({type, children, props}) => {
  const element = document.createElement(type);

  if (props) {
    for (const prop in props) {
      element.setAttribute(prop, props[prop]);
    }
  }

  if (children) {
    if (Array.isArray(children)) {
      children.forEach(child => {
        if (typeof child === 'string') {
          element.innerText = child;
        } else {
          element.appendChild(render(child));
        }
      })
    } else if (typeof children === 'string') {
      element.innerText = children;
    } else {
      element.appendChild(render(children));
    }
  }

  return element;
}
Enter fullscreen mode Exit fullscreen mode

然后,让我们创建这个h函数。

const h = (type, children, props) => {
  let handledType = typeof type === 'string' ? type : 'div';

  return {
    type: handledType,
    props,
    children
  }
}
Enter fullscreen mode Exit fullscreen mode

最后,让我们用我们的h函数创建一个实际的内容,用我们的函数渲染它render并将结果安装到 DOM。

const div = render(
  h('div',
    [ 
      h('h1', 'Hello!', { id: 'foo' }),
      h('h2', 'World!', { class: 'bar' })
    ],
  )
);

document.querySelector('#app').appendChild(div);
Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/fromaline/hyperscript-the-hidden-language-of-react-3d1f
PREV
使用 Next.js、MUI 和 react-query 实现分页
NEXT
Osome 是如何从 Javascript 和 Flow 迁移到 TypeScript 的