JSX实际上非常简单:花1分钟阅读一下,您将了解到有关模板的有趣替代方法的所有知识。
替代标题:“与JSX一起生活”
语用
您可以声明每个文件或每个函数的名称,以告知您的编译器(例如Babel)在运行时应为每个节点调用的函数的名称(请参见Transpilation)。
在下面的示例中,我们说的是“h()
为每个节点注入对函数的调用”:
/** @jsx h */
转译
如果您还没有使用转译器,应该使用。使用ES6 / ES2015时,编写,调试,测试和运行JavaScript更加有效。Babel是那里最受欢迎和推荐的转译器,所以我认为这就是您所使用的。
除了将您的ES6 / ES7 +语法转换为当今的JavaScript之外,Babel还包括对JSX的编译支持 <mark style="background: rgb(253, 255, 182); color: rgb(0, 0, 0);">开箱即用</mark>。您无需添加或更改任何内容即可使用此功能。
通过看一个非常简单的示例,最容易看出它是如何工作的:
之前:( 您编写的代码)
/** @jsx h */
let foo = <div id="foo">Hello!</div>;
之后:( 您运行的代码)
var foo = h('div', {id:"foo"}, 'Hello!');
您可能正在看第二个代码片段,以为使用功能构建UI并不会太糟糕...
这就是为什么我开始加入JSX的原因:如果它从地球上消失了,用手编写输出仍然会很舒适。
JSX只是已经相当不错的语法的糖。**
人们甚至将其用于整个项目:超标
让我们构建一个JSX渲染器
首先,我们需要定义h()
转译代码正在调用的函数。
您可以随心所欲地调用它,h()
因为这种类型的“构建器”功能的原始想法被称为hyperscript(“文本“ +”爪哇脚本”)。
function h(nodeName, attributes, ...args) {
let children = args.length ? [].concat(...args) : null;
return { nodeName, attributes, children };
}
好的,那很容易。
不熟悉ES6 / ES2015?
- 这
...
在参数列表是一个休息PARAM。它将参数的“其余”收集到一个数组中。- 该
concat(...args)
位是一个散布运算符:它采用该Array并将其扩展为concat()
。的参数。concat()
这里的用途是折叠子节点的任何嵌套数组。
现在我们有了这些嵌套的JSON对象,我们的h()
函数就会退出,因此我们最终得到了像这样的“树”:
{
nodeName: "div",
attributes: {
"id": "foo"
},
children: ["Hello!"]
}
因此,我们只需要一个接受该格式并吐出实际DOM节点的函数:
function render(vnode) {
// Strings just convert to #text Nodes:
if (vnode.split) return document.createTextNode(vnode);
// create a DOM element with the nodeName of our VDOM element:
let n = document.createElement(vnode.nodeName);
// copy attributes onto the new node:
let a = vnode.attributes || {};
Object.keys(a).forEach( k => n.setAttribute(k, a[k]) );
// render (build) and then append child nodes:
(vnode.children || []).forEach( c => n.appendChild(render(c)) );
return n;
}
甜。不难理解它是如何工作的。
如果有帮助,您可以将“虚拟DOM”视为如何构建给定DOM结构的非常简单的配置。
虚拟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 <body>:
document.body.appendChild(dom);
局部,迭代与逻辑:无新语法
除了使用模板语言引入的有限概念之外,我们还提供了所有JavaScript。
“部分”是无逻辑/有限逻辑模板引擎引入的概念,用于跨不同上下文重用视图的块。
迭代是每种新的模板语言似乎都重新发明的东西(我和任何人一样内)。使用JSX,无需学习一次性语法:迭代JavaScript程序中的其他位置。你选择的迭代风格,最适合给定任务:[].forEach()
,[].map()
,for
和while
循环等
逻辑就像迭代一样,是模板语言喜欢重新发明的东西。一方面,无逻辑模板提供了将逻辑嵌入到视图中的非常差的方法:有限的构造(例如{{#if value}}
将逻辑推送到控制器层中),令人肿。这样可以避免构建用于描述更复杂逻辑的语言,从而避免了可预测性和安全性陷阱。
另一方面,使用代码生成的引擎(从粗略到不可原谅的技术范围)通常拥有执行任意JavaScript表达式以进行逻辑甚至迭代的能力。这是一个不惜一切代价避免这种情况的充分理由:您的代码被从其原始位置(可能是模块,闭包或标记内)中剥离出来,并在“其他位置”进行了评估。这对我来说是无法预料或不够安全的。
JSX允许使用JavaScript的所有语言功能,而无需在构建步骤中以及在没有
eval()
&朋友的情况下依赖于生成怪诞的代码。
// Array of strings we want to show in a list:
let items = ['foo', 'bar', 'baz'];
// creates one list item given some text:
function item(text) {
return <li>{text}</li>;
}
// a "view" with "iteration" and "a partial":
let list = render(
<ul>
{ items.map(item) }
</ul>
);
render()
返回DOM节点(<ul>
在上述情况下为),因此我们只需要将其放入DOM中即可:
document.body.appendChild(list);
把它放在一起
这是小型虚拟DOM渲染器的完整资源以及使用它的视图。
下面提供带有某些样式的CodePen。
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> )
);
网友评论