[译] JSX 的替代方案

现在,JSX 已是一个很是受欢迎的框架模版了,它的应用也不只仅局限于 React(或其余 JSX 衍生模版)。可是,若是你并不喜欢它,或者有某些想要避免使用它的项目,或者只是好奇不使用 JSX 该如何书写 React 代码的时候,该怎么办呢?最简单的方法就是去阅读官方文档,可是,官方文档很简短,而在本篇文章中咱们为您提供了更多的选择。html

免责声明:我的来讲,我很喜欢 JSX,在我全部的 React 项目中我都使用了它。可是,我对本文主题从新进行了调研,而且但愿和你分享个人所见。前端

什么是 JSX

首先,咱们须要明白什么是 JSX,这样咱们才能在纯 JavaScript 中编写对应的代码。JSX 是一种特定域编程语言,意味着咱们须要将 JSX 代码转码,以便获得常规的 JavaScript,不然浏览器将没法解析代码。展望前景光明的将来,若是你想要使用 modules,而且全部须要的功能都能被目标浏览器支持,你仍然不能彻底丢弃转码这一步,这多是一个问题。node

也许理解 JSX 将会被解析成什么最好的方法就是使用 babel repl 实际操做一次。你须要点击左侧面板的 presets 而且选择 react,这样解析器才能正确的解析代码。这以后,你就能在右侧实时看到编译生成的 JavaScript 代码。例如,你能够尝试下这段代码:react

class A extends React.Component {
    render() {
        return (
            <div className={"class"} onclick={some}>
                {"something"}
                <div>something else</div>
            </div>
        )
    }
}
复制代码

个人运行结果以下:android

class A extends React.Component {
  render() {
    return React.createElement("div", {
      className: "class",
      onclick: some
    }, "something", React.createElement("div", null, "something else"));
  }
}
复制代码

能够看到,每一个 <%tag%> 结构都被替换成了函数 React.createElement。第一个参数是 react 组件或者内建标签名字符串(好比 divspan),第二个参数则是组件属性,其余的参数则都被视做组件的子元素。ios

我强烈推荐你使用不一样结构的组件树反复尝试,来观察 React 如何渲染值为 truefalse、数组、或者组件等的属性:即便你只尝试使用 JSX 和一些其余内容的代码,它也颇有帮助。git

若是你想深刻学习 JSX,能够参考官方文档github

重命名

因为编译结果是固定的,咱们其实也能够将全部的 React 代码直接以这种形式写出,可是其实这种方式存在一些问题。web

第一个问题就是很是繁琐。真的至关繁琐,而罪魁祸首就是 React.createElement。因此这个问题的解决方案就是将它简写为一个变量,按照 hyperscript 的方式命名为 h。这种方式能节省不少代码量,而且可读性也更强。下面咱们来重写上面的代码,以便说明:编程

const h = React.createElement;
class A extends React.Component {
  render() {
    return h(
      "div",
      {
        className: "class",
        onclick: some
      },
      "something",
      h("div", null, "something else")
    );
  }
}
复制代码

Hyperscript

若是 React.createElement 或者 h 你都已经尝试过了,你就能够看出它们都存在一些缺点。首先,函数须要三个参数,因此在没有属性的状况下,你仍是必须传递 null 做为参数,同时,className 做为一个很经常使用的属性,在每次使用的时候都须要新建一个对象。

做为一个替代方案,你可使用 react-hyperscript 库。它不须要你提供空属性,而且容许你用点号的方式定义 class 和 id(div#main.content -> <div id="main" class="content">)。这样,你的代码能优化为:

class A extends React.Component {
  render() {
    return h("div.class", { onclick: some }, [
      "something",
      h("div", "something else")
    ]);
  }
}
复制代码

HTM

若是你并不反感 JSX 自己,可是不喜欢必需的代码编译,那么你能够试试看 htm 这个项目。它的目标就是完成和 JSX 相同的事情(而且代码看上去也相同),可是使用的是模版字符串。它可能会带来一些开销(由于须要在运行时将模版解析),可是在某些状况下也许也是值得的。

它的工做方式是将元素函数包裹起来,也就至关于前面例子中的 React.createElement,可是它支持任何其余具备相似 API 的库,同时仅在运行时编译模版并返回和 babel 编译结果同样的代码。

const html = htm.bind(React.createElement);
class A extends React.Component {
    render() {
        return html`
            <div className=${"class"} onclick=${some}>
                ${"something"}
                <div>something else</div>
            </div>
        `
    }
}
复制代码

如你所见,结果几乎和 JSX 同样,只是咱们须要以略微不一样的方式插入变量;可是,大部分区别都是很细节的地方,若是你想要展现如何不使用任何构建工具来使用 React,这个工具就很方便。

类 Lisp 语法

它的核心思想和 hyperscript 很相似,但它采用了一个很优雅的方式,值得一看。现现在,有不少相似的帮助库,因此到底选择哪一个也因人而异;而它们都有可能能给你的项目带来些灵感。

ijk 这个库的思路是只用数组来写模版,并将位置做为参数。这样写的优点在于你不须要老是写 h(是的,有时候总写 h 也会让人以为很冗余!)。以下是一个使用案例:

function render(structure) {
  return h('nodeName', 'attributes', 'children')(structure)
}
class A extends React.Component {
  render() {
    return render([
      'div', { className: 'class', onClick, some}, [
        'something',
        ['div', 'something else']
      ]]);
  }
}
复制代码

总结

这篇文章并非建议你不使用 JSX,也不是说 JSX 有什么很差。可是你可能会好奇若是不用它,你要怎么写代码,还有你的代码可能会是什么样子,本文的目的就只是回答了这个问题。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索