构建本身的React:(2)Element creation and JSX

Didact: Element creation and JSX

翻译自这里:https://engineering.hexacta.c...javascript

JSX

上一节咱们介绍了Didact Elements,使用了一种很麻烦的方法来表明要渲染的DOM。这一节咱们将介绍如何使用JSX来建立Didact Elements。java

下面是一个Didact Elements的原生对象表示:node

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" } }]
        }
      }
    ]
  }
};

有了JSX这个语法糖以后咱们就可使用下面这个方法来建立和上面同样的元素:git

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不熟悉你能够能会想上面这段代码是个无效的JS对象-----没错,你想的是对的。为了让浏览器能解析JSX,咱们须要使用预处理器(好比babel,想对JSX有更多了解的能够看这里)来将JSX转换一下。例如babel会将上面的JSX转成下面这个样子:github

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"
  )
);

剩下咱们要作的就是添加一个createElement方法来让Didact支持JSX,其余的工做就能够交给预处理器了。createElement方法的第一个参数是元素的类型type,第二个参数是元素的props对象,剩下的其余参数就是children了。createElement方法会返回带有type属性和props属性的对象,props属性值也是一个对象,该对象含有第二个参数的全部属性,第二个参数以后的其余参数会放在一个数组中,并做为该对象的children属性值。来实现一下createElement方法:算法

function createElement(type, config, ...args){
    const props = Object.assign({}, config);
    const hasChildren = args.length > 0;
    props.children = hasChildren ? [].concat(...args) : [];
    return {type, props}
}

上面的createElement在不碰到文本元素时都能很好的工做。遇到文本元素时,文本内容会以字符串形式在第二个参数以后传递给createElement。又由于咱们以前定义了文本元素也须要有typeprops属性,因此咱们会将刚传进来的字符串转成一个文本元素。数组

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));
    return { type, props };
}

function createTextElement(value){
    return createElement(TEXT_ELEMENT, { nodeValue: value});
}

上面代码排除了子元素为nullundefinedfalse的状况。这些状况都是不必渲染的,因此也不须要添加到props.children上。浏览器

Summary

这一节咱们依然没有添加主功能到Didact上,但如今咱们已经开始使用JSX来建立元素了,这大幅提高了开发体验。我已经将上节和本节的代码在codepen上更新了。代码头部的注释/** @jsx crerateElement8/告诉了babel去使用createElement来转义JSX。babel

你也能够在这里查看代码dom

下一节咱们将往Didact中加入虚拟DOM和用来支持更新操做的一致性校验算法。

下一节

相关文章
相关标签/搜索