JSX是什么鬼(WTF-is-JSX)

What the fuck!?(骂人词语,或表示惊吓、错愕、不满...等反应)
更新于: 2023-11-03 19:43:48

Pragma

编译指示; 注解; 实际型; 编译附注; 编译器指挥模组;

您可以声明每个文件或每个函数来告诉您的transpiler(例如:Babel每个节点在运行时应调用的函数的名称(请参阅“Transpilation”)。

在下面的例子中,我们说的是“ h()为每个节点注入一个函数”:

/** @jsx h */

Transpilation

如果你还没有使用解析器,你应该是尝试一下。使用ES6 / ES2015 编写,调试,测试和运行JavaScript时更为高效。Babel是最受欢迎和推荐的解析器,所以我会假设你正在使用它。

你可以在这里在线测试代码。

/** @jsx h */
let foo = <div id="foo">Hello!</div>;
var foo = h('div', {id:"foo"}, 'Hello!');
babel转换JSX

我们来构建一个JSX渲染器

你调用任何你想要的,我使用h(),因为这种类型的“构建器”功能的原始想法被称为 hyperscript (“hypertext“ + “javascript”).。

function h(nodeName, attributes, ...args) {
  let children = args.length ? [].concat(...args) : null;
  return { nodeName, attributes, children };
}

现在我们有这些嵌套的JSON对象我们的h()函数吐出来,所以我们最终得到一个这样的“树”

const vdom = {
  nodeName: "div",
  attributes: {
    id: "foo",
  },
  children: ["Hello!"],
};

所以我们只需要一个接受该格式并抛出实际 DOM 节点的函数:(即沉染 vdom )

function render(vnode) {
  // 字符串只转换成 文本节点:
  if (vnode.split) return document.createTextNode(vnode);
  // 使用 VDOM 的 nodeName 创建一个DOM 标签
  let n = document.createElement(vnode.nodeName);
  // 拷贝所有属性到新节点上
  let a = vnode.attributes || {};
  Object.keys(a).forEach((k) => n.setAttribute(k, a[k]));
  // 渲染并添加子节点
  (vnode.children || []).forEach((c) => n.appendChild(render(c)));
  return n;
}

VDOM的优点

  • 虚拟DOM的好处是它非常轻巧。小对象引用其他小对象,一个由易于优化的应用程序逻辑构成的结构。
  • 这也意味着它不受任何渲染逻辑或缓慢的DOM方法的束缚。

使用JSX

我们知道JSX被转换成 h() 函数调用。 那些函数调用创建一个简单的“虚拟” DOM 树。 我们可以使用该 render()函数来制作一个匹配的“真实”DOM树。 这就是这样的:

// JSX -> VDOM:
let vdom = <div id="foo">Hello!</div>;
// VDOM -> DOM:
let dom = render(vdom);
// add the tree to :
document.body.appendChild(dom);

一个相对完整的,我写的在 example/babel-jsx

const ITEMS = "hello there people".split(" ");

// turn an Array into list items:
let list = (items) => items.map((p) => <li> {p} </li>);

// view with a call out ("partial") to generate a list from an Array:
let vdom = (
  <div id="foo">
    <p>Look, a simple JSX DOM renderer!</p>
    <ul>{list(ITEMS)}</ul>
  </div>
);

// render() converts our "virtual DOM" (see below) to a real DOM tree:
let dom = render(vdom);

// append the new nodes somewhere:
document.body.appendChild(dom);

// Remember that "virtual DOM"? It's just JSON - each "VNode" is an object with 3 properties.
let json = JSON.stringify(vdom, null, "  ");

// The whole process (JSX -> VDOM -> DOM) in one step:
document.body.appendChild(render(<pre id="vdom">{json}</pre>));

参考