構建本身的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和用來支持更新操做的一致性校驗算法。

下一節

相關文章
相關標籤/搜索