JSX是什么鬼(WTF-is-JSX)
What the fuck!?(骂人词语,或表示惊吓、错愕、不满...等反应)
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!');
我们来构建一个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>));