React 剛發布的時候,很多人才看了一眼,然后就有點接受不了。JavaScript 里的那些尖括號是干啥用的?!淦,說好的分離呢?Facebook 到底有沒有從社區學到教訓?
跟很多人一樣,我一開始對于 React's JSX 的這種做法到底有沒有效,也是將信將疑,這點還是可以肯定的。但現在我已經愛上 JSX 了,每當我向新人推薦它,都感覺像在炫耀自己實際長得一點都不好看的兒子。
這里有一張作者兒子的照片,還是很可愛的。(我是圖片)
除了標簽和 JavaScript 混寫外,我知道 JSX 也不是一個徹底的方案。實際上,它就是硬幣的另一面,跟事物發展到某種程度就會出現的東西一樣。想知道為什么,搬好椅子,我要開始講(zhuang)課(bi)了。
第一階段:沒什么存在感的 JavaScript (Unobtrusive JavaScript)
還記得過去 jQuery 的大好時光嗎?到處都是選擇器和 DOM 操作。這時,標簽是單純的標簽,腳本是單純的腳本。嗯,這感覺還不錯。
我們會像這樣寫標簽:
<a class="hide">click me to hide</a>
像這樣寫腳本:
$('.hide').click(function() {$(this).hide();})
這樣就可以下班了?并沒有。
似乎是個不錯的方案呢~ 我們的標簽很純粹!問題隨之而來,我怎么在腳本里找到關于這個標簽的所有邏輯呢?答:通讀腳本,一行不漏。在某些極端條件下,你都不能隨便動 DOM tree 結構,可能導致某些選擇器失效,除非你通讀代碼。You see? 分離沒有想象中的簡單。腳本和標簽的確是在各自的文件里,而實際上它們已經緊緊相擁在一起。新的維護人員必須看懂以前的人寫的所有代碼,否則容易炸(the guy who wrote these codes was gone ...)
嚴格遵守分離原則,帶來的只有痛苦的維護和 debug 體驗。每次你想改內容,都得擔心會不會又有哪個選擇器失效?;蛟S從一開始就走錯了方向,放下對分離原則的偏執,或許能更愉快地開發?
第二階段:雙向綁定
當前端們在 Knockout 和 Angular 里第一次見到雙向綁定,好比約伯受盡千辛萬苦見到耶穌。我們之中很多人毫不猶豫立刻拋棄了對分離原則宗教般的信仰,投奔聲明式綁定的懷抱(直接在標簽里聲明:v-if v-else ng-for ......)。數據層變,UI 也跟著變;UI 變,數據層也跟著變。很干凈,很明了。
每個庫或框架都有它自己用來實現雙向綁定的方式,但本質上做的都是同一件事情。先看看下面這幾個來自比較流行的框架里的遍歷數組的例子:
// Angular
<div ng-repeat="user in users">
// Ember
{{#each user in users}}
// Knockout
data-bind="foreach: users"
這里發生了一些有趣的事。很少人意識到這個根本問題:我們正努力地把腳本嵌進標簽里,而不是分離。這幾個例子實現的都是同一件事情:通過添加額外的屬性來增強原生標簽,借由腳本來解析實現?,F在,我們能愉快地把腳本和標簽以這種方式寫在一起,是時候介紹 React: 硬幣的反面了。
第三階段:JSX
React 的 JSX 不夠徹底,它也不過是這個想法所產生的成果之一:業界達成共識,標簽和腳本應該放在一起。誠然,我們的宣傳不夠廣泛。但只要你用過 Angular,Knockout,Ember 就能明白這個新方向了。像我上面所演示的,數據綁定式的標簽寫法就是不斷地把腳本寫到標簽里。既然已經選擇腳本標簽混寫,為什么還要加到 HTML 這種不嚴謹、松散、軟弱無力的語言里呢?從一開始,瀏覽器對 HTML 的解析就很寬容,也不嚴謹。那么 HTML 還有實現聲明數據綁定,變量遍歷,邏輯判斷的嚴謹的結構基礎嗎?
Facebook 認識到這點,JavaScript 更有邏輯,也是一門不錯的語言來解決這兩者混寫時遇到的問題。這時候,轉變再次發生:
Angular,Ember 和 Knockout 把 JavaScript 放到 HTML 里,React 把 HTML 放到 JavaScript 里
這一舉措帶來的益處是多方面的,直到你用上了 React 和 JSX 很久之后才能深刻體會到。React 的 JSX 完勝階段二里提到的所有技術,因為以下理由:
編譯時報錯
當你在 HTML 里拼錯,你根本不知道哪里有問題。很多情況下,就是個被忽略了的運行時錯誤。例如:用 Angular 的時候,你把 ng-repeat 寫成 n-repeat,頁面什么都沒發生;用 Knockout 時,把 data-bind 寫成 data-bnd 也一樣。它們能跑起來,但不會報錯。
相反,如果你在 JSX 里拼錯一個字母,它就編譯不了。忘記關閉 li 標簽?你難道不希望在寫 HTML 的時候獲得更豐富的反饋?
JSX 讓這種必要的反饋成為了現實!這個舉措的重要性怎么強調也不過分。快速反饋能大幅提升生產力。像我在 Clean Code 課上講到的:越快報錯的方案,就是越好的方案。
解放 JavaScript 的所有潛能
把標簽和腳本寫在一起,意味著你能夠享受 JavaScript 帶來的所有便利,以及更嚴謹的標簽,不像以 HTML 為基礎的框架,類似Angular(應該指 1.0 版本)和 Knockout 那樣只提供部分功能。
客戶端框架(Angular 1 Knockout ...)不應該需要學習額外語法來循環聲明以及條件判斷。(雖然語法形式都類似)
React 避免了這點,而階段二中提到的技術,各有各的語法形式。與此相反,JSX 看起來跟 HTML 挺像的,除了它用的是原生的 JavaScript 寫法(剛開始看起來,確實有點不適應)。在一個以 JavaScript 為基礎的生態圈里,不用學全新語法確實不錯。
JSX,很多 IDE 已經有智能提示。以 HTML 為基礎的很多框架還不能做到這一點
最后
JSX 的產生并不是無中生有,它是自然過程的一個階段,所以無法逃避
(老文渣翻)
原文地址:https://medium.com/@housecor/react-s-jsx-the-other-side-of-the-coin-2ace7ab62b98