標籤:

說說對react中JSX語法的理解?


我感覺JSX經常被無端無腦黑,其實JSX相比模版是有很多明顯優勢的。所以認真回答一下。

普通的字元串模版有很多問題:

1. 丟掉了JavaScript本身語言的能力

還記得用n個ng-if替代一個簡單的else的時候嘛?後來又搞了一堆switch來解決這個問題,最後也沒能簡單有效地表達else。 因為要表達else就要設計表達式規則和塊級作用域等等。給html設計優先順序還是非常蛋疼的。JSX本來就是對象,對象就是表達式的一種,想else直接用JS本來的表達式就好了,既不用學更多的語法API,能力也和JS很好地保持一致。

很多模版還得在很多屬性後面自己解析AST,並且還得嘗試靠近JS表達式的語義,大部分的時候這些表達式本身能力受限,還不能隨便到處用。JSX寫哪都一樣,反正本來就是JS。

2. 非靜態編譯,把錯誤保留到運行時。

你用Webpack用了一個忘定義或者忘import的變數,編譯直接就掛了。JSX因為就是JS,所以也是一樣的。字元串模版就得等到運行時觸發這個組件的時候才會發現這個組件undefined然後掛掉。

某些模版為了克服這些缺點費了很大勁來確保編譯檢查,到頭來其實還是重新發明了JS。

3. 體積大。JS壓縮是再常見不過的事,JSX只是調用了React.createElement或者h這些pragma。壓縮都是白送的,模版還是一樣,非好大勁優化也就跟JSX接近。

另外JSX本身是一個非常巧妙的設計:

1. XML,很多人一提XML就生理不適。選XML有兩點,一個是HTML本來就是XML,因此你用模板也是一樣的,除非搞Jade之類的其他模板。另外XML本身就是一個難寫版的S-expression,非常適合用來表示這種UI結構。至於為啥不用S-exp,因為原語是HTML不是Lisp。

2. 本身就是JS,暴露一個pragma搞定。整個體系非常好理解,tag就是調用,屬性就是傳參,也沒坑。實在搞不懂編譯一下就知道了。

3. 可組合性。一堆嵌套的JSX就是表達式樹。大部分模板嵌套起來都有限制,沒JSX嵌套起來自由。

4. JSX提高了模板的抽象程度。Cheng Lou提到模板本質是Data,抽象程度較低,導致你經常需要重複代碼。這時就要把它的抽象程度提高,最簡單的方法就是JSX這種描述性的對象,可以被函數返回,這就借用了函數帶來的的一切抽象能力。

同理,CSS抽象程度也低,經常不得不重複代碼,到頭來跟模板一樣發明好多方言預編譯甚至方法論來解決問題。CSS本來長得就像JS對象,就讓他變成JS對象,也可以被函數加持。

怎麼樣,是不是很多依賴運行時值,寫不成純CSS的需求一下簡單多了?所以所謂HTML,JS,CSS分離關注點的粗暴方式都是偽命題。優雅的分離不是這麼強行分家的。

所以你只要會JS和HTML兩個原語,一下就能掌握JSX。模板搞了半天只會面臨各種問題,越來越複雜,最終要解決完所有問題基本也就把JS重寫了一遍(是不是很像「格林斯潘第十定律」),這個問題被FB用JSX這種方法一下就解決了。某些高端框架把編譯搞得巨複雜最後也只是為了彌補設計不夠簡練的坑。

另外,主流用模版的框架,這種模版加class沒法很好地和函數結合。這個不是模版本身的問題,比如play framework的模版也用的函數的心智模型。但是比如常見的把模版放在decorator上的方式,等於把view放在了partial apply的參數里,卻把model放在下面,導致復用性變差。

上面這段怎麼理解呢?就是類似為什麼Haskell的map順序和JS等主流語言的順序不一樣的問題:

  1. [1, 2, 3].map(x =&> x + 1)
  2. map (+1) [1, 2, 3]
  3. 為了方便對比,我們把1換成lodash的map([1, 2, 3], x =&> x + 1)

發現問題了嘛?假設函數都是科里化的,如果map先接受[1, 2, 3],你的要操作的數據就是[1, 2, 3],你傳別的東西都是操作這個具體數據的,所以你得到的這個結果就只能應用不同的函數,這樣抽象程度低,復用差。如果map先接受x =&> x + 1,那你就免費得到了一個介於map和increment 1,2,3之間的一個map increment的中等抽象概念。這個中等抽象概念可以被任何的具體數據使用。

所以HOC就么回事。你@connect的表達式結果可以被任何需求這些props的組件使用。甚至可以連續connect,把每一件事情都變成可組合的。

反過來在decorator上compose多個模板根本不make sense。

還有上面提到的Cheng Lou關於抽象的視頻,能科學上網的強烈推薦。https://www.youtube.com/watch?v=mVVNJKv9esE

裡面提到了某些框架抽象不均勻的問題,比如框架整體大而全的方式導致了過高的學習成本,同時在模板這些關鍵部位卻缺乏有效抽象。很好地講解了FB設計代碼背後的哲學。

以上。話說回來,設計得好壞,只要能跑的,都可以用來幹活。但大巧不工,設計上的差距會讓很多細節分出好壞。FB幾個四兩撥千斤的設計,直接抵消了很多無用的工作,還同時讓所有東西保持其本來應該的簡單。達到這種效果並不容易,這背後的功底和境界是值得我們學習的。


所謂語法,無非就是寫法不一樣而已,表達的內容都是一樣的。

我在學習React之前對jsx語法也抱有看法,但是寫兩個星期就習慣了。

我也用過Vue,我覺得比起模板指令,用js控制html更靈活一些。


抽象程度更加底層的模板,依託js,靈活度極高,賦予開發者最大的自由,也因此,不同的開發者寫出來的代碼質量和風格相差較大,團隊協作時,可維護性相對較差,需要高素質的開發團隊。理念很好,但從發展方向來看,漸漸偏離傳統web的發展方向和理念,如web component,shadow dom等。jsx不會成為主流,但會有很多人喜歡它


推薦閱讀:

為什麼 React 推崇 HOC 和組合的方式,而不是繼承的方式來擴展組件?

TAG:React |