JSX实际上非常简单:花1分钟阅读本文,您将了解关于这个模板替代方案的所有内容。
备选标题:“使用JSX”
Pragma
你可以通过文件或函数声明这个指令,告诉你的转译器(例如:Babel)为每个节点调用。
在下面的例子中,我们说“为每个节点注入 h() 函数的调用”:
/** @jsx h */
Transpilation
如果你还没有使用转译器。在你使用ES6/ES2015,你可以感觉到编写、调试、测试和运行JavaScript都更加有效。Babel是广受受欢迎转译器,我假设您正在使用它。
除了将ES6/ES7语法转换为低版本javascript之外,Babel还包括对编译JSX支持。您不需要添加或更改任何内容即可使用此功能。
通过一个非常简单的例子,我们可以很容易地看出是如何工作的:
Before:
/** @jsx h */
let foo = <div id="foo">Hello!</div>;
After:
var foo = h('div', {id:"foo"}, 'Hello!');
你可能会看着第二个代码片段,认为使用函数构建UI并没有那么糟糕……
这就是我开始使用JSX的原因。
让我们构建一个JSX渲染器
首先,我们需要定义代码调用的 h() 函数。
您可以将其命名为任何您想要的名称,我使用 h() ,因为这种类型的“构建器”函数的原始想法被称为hyperscript("hypertext" + "javascript")
function h(nodeName, attributes, ...args) {
let children = args.length ? [].concat(...args) : null;
return { nodeName, attributes, children };
}
现在h() 函数返回了嵌套的JSON对象:
{
nodeName: "div",
attributes: {
"id": "foo"
},
children: ["Hello!"]
}
所以我们只需要一个函数来接受这种格式并输出实际的DOM节点:
function render(vnode) {
// 字符串只需转换为#text节点:
if (vnode.split) return document.createTextNode(vnode);
// 使用我们的VDOM元素创建一个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;
}
不难理解这是怎么回事。
使用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 <body>:
document.body.appendChild(dom);
把它放在一起
下面是这个小虚拟DOM渲染器的完整源代码和使用它的视图。
const ITEMS = 'hello there people'.split(' ');
// 将数组转换为列表项:
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()将我们的“虚拟DOM”转换为真正的DOM树:
let dom = render(vdom);
// 将新节点附加到某处:
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> )
);