- 原文地址:Alternatives to JSX
- 原文做者:Seva Zaikov
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:EmilyQiRabbit
- 校對者:xionglong58,sunui
現在,JSX 已是一個很是受歡迎的框架模版了,它的應用也不只僅侷限於 React(或其餘 JSX 衍生模版)。可是,若是你並不喜歡它,或者有某些想要避免使用它的項目,或者只是好奇不使用 JSX 該如何書寫 React 代碼的時候,該怎麼辦呢?最簡單的方法就是去閱讀官方文檔,可是,官方文檔很簡短,而在本篇文章中咱們爲您提供了更多的選擇。html
免責聲明:我的來講,我很喜歡 JSX,在我全部的 React 項目中我都使用了它。可是,我對本文主題從新進行了調研,而且但願和你分享個人所見。前端
首先,咱們須要明白什麼是 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 組件或者內建標籤名字符串(好比 div
或 span
),第二個參數則是組件屬性,其餘的參數則都被視做組件的子元素。ios
我強烈推薦你使用不一樣結構的組件樹反覆嘗試,來觀察 React 如何渲染值爲 true
、false
、數組、或者組件等的屬性:即便你只嘗試使用 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")
);
}
}
複製代碼
若是 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")
]);
}
}
複製代碼
若是你並不反感 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,這個工具就很方便。
它的核心思想和 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 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。