Skip to content

Latest commit

 

History

History
136 lines (102 loc) · 5.02 KB

2.JSX.md

File metadata and controls

136 lines (102 loc) · 5.02 KB

2. 元素创建和JSX

这个故事是我们一步一步构建自己版本的React的系列文章的一部分:

2.1 JSX

上次我们介绍了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"
  )
);

>> babel repl

我们需要添加到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

2.2 概要

在这篇文章中我们没有给Didact增加任何实际的权力,但是我们现在有了改进的开发者体验,

因为我们可以使用JSX来定义元素。我已经更新了上次的codepen以包含来自这篇文章的代码。

请注意,codepen使用babel来传输JSX,开头的注释/** @jsx createElement */告诉babel使用函数。

您还可以检查Github提交的更改。


在下一篇文章中,Didact: Instances, reconciliation and virtual DOM |-|_|🌟| 我们介绍了Didact的虚拟DOM和对比算法以支持DOM更新