这个故事是我们一步一步构建自己版本的React的系列文章的一部分:
上次我们介绍了Didact Elements,它是一种描述我们想要呈现给-DOM-的非常详细的方式{数据结构}
。
在这篇文章中,我们将看到如何使用JSX
来简化元素的创建。
JSX
提供了一些语法糖来创建元素。以便代替:
const element = {
type: "div",
props: {
id: "container",
children: [
{ type: "input", props: { value: "foo", type: "text" } },
{
type: "a",
props: {
href: "/bar",
children: [{ type: "TEXT ELEMENT", props: { nodeValue: "bar" } }]
}
},
{
type: "span",
props: {
onClick: e => alert("Hi"),
children: [{ type: "TEXT ELEMENT", props: { nodeValue: "click me" } }]
}
}
]
}
};
我们的代码可以是
const element = (
<div id="container">
<input value="foo" type="text" />
<a href="/bar">bar</a>
<span onClick={e => alert("Hi")}>click me</span>
</div>
);
如果你对JSX
不熟悉,你可能会想知道最后一个片段是否是有效的javascript:
它不是。
为了使浏览器的理解,需要的代码由预处理转化为-有效的JS,像babel了解更多关于JSX阅读这篇文章由贾森·米勒。
例如,babel
从上面将JSX转换为:
const element = createElement(
"div",
{ id: "container" },
createElement("input", { value: "foo", type: "text" }),
createElement(
"a",
{ href: "/bar" },
"bar"
),
createElement(
"span",
{ onClick: e => alert("Hi") },
"click me"
)
);
我们需要添加到Didact
中来支持JSX
是一个createElement
功能,这就是其余部分工作由-预处理器-完成的。
函数的第一个参数是type
元素的第一个参数,第二个参数是元素的对象props
,以及所有下面的参数children
。
createElement
需要创建一个props
对象,将其分配给第二个参数中的所有值,将该children
属性设置为第二个参数后面的所有参数,然后返回一个对象{}
- 带有 {type, props }
。把它放到代码中更容易:
function createElement(type, config, ...args) {
const props = Object.assign({}, config);// 合并
const hasChildren = args.length > 0; // 孩子?
props.children = hasChildren ? [].concat(...args) : [];
return { type, props }; // Didact元素的数据结构-类型{type}与属性{props}
}
除了一件事情之外,这个函数运行良好:文本元素
。
文本-作为字符串-传递给createElement
函数,Didact
需要文本元素type
以及props
其余元素。
所以我们将每个arg
转换为一个文本元素-一个规范的`Didact元素:
const TEXT_ELEMENT = "TEXT ELEMENT"; // 类型
function createElement(type, config, ...args) {
const props = Object.assign({}, config);
const hasChildren = args.length > 0;
const rawChildren = hasChildren ? [].concat(...args) : [];
props.children = rawChildren
.filter(c => c != null && c !== false)
.map(c => c instanceof Object ? c : createTextElement(c));
// 过滤-空-值, 剩下的-不属于-Object的值 -> createTextElement -> 变为 类型为TEXT_ELEMENT- Didact元素
return { type, props };
}
function createTextElement(value) {
// 规范数据
return createElement(TEXT_ELEMENT, { nodeValue: value });
}
我还筛选了要排除的子项列表null,undefined并指出false
.
我们不会呈现这些子项,因此不需要添加
它们props.children
。
在这篇文章中我们没有给Didact
增加任何实际的权力,但是我们现在有了改进的开发者体验,
因为我们可以使用JSX
来定义元素。我已经更新了上次的codepen以包含来自这篇文章的代码。
请注意,codepen
使用babel来传输JSX
,开头的注释/** @jsx createElement */
告诉babel
使用函数。
您还可以检查Github提交的更改。
在下一篇文章中,Didact: Instances, reconciliation and virtual DOM |-|_|🌟| 我们介绍了Didact的虚拟DOM和对比算法以支持DOM更新