我們想要創(chuàng)建一個組件卵酪,首先需要理解一個重要的概念:JSX
const element = <h1>Hello, world!</h1>;
這種類似于html代碼的東西就是JSX
。我們可以簡單的將其理解為一種渲染數(shù)據(jù)的模板語言非竿。有接觸過其他模板語言的同學(xué)應(yīng)該知道嚷掠,模板語言其實是為了簡化直接調(diào)用DOM API來渲染數(shù)據(jù)的復(fù)雜度,模板語言的本質(zhì)仍然是JS代碼取募。記住這個特性,在理解虛擬DOM這個重要概念時會大有幫助蟆技。
在React的組件中玩敏,只有引入了React的模塊才能正確識別JSX
代碼。
// 必不可少
import React from 'react';
JSX與html非常類似质礼,因此如果你對html已經(jīng)非常熟悉的話旺聚,使用JSX就非常簡單。但除此之外眶蕉,JSX還具有模板語言的特性砰粹。
- 可以在JSX中使用表達式
const ele = <h1>Hello, {name}!</h1>
const ele = <h1>{sayHello('alex')}!</h1>
const ele = <h1>{condition ? 'React' : 'React Native'}!</h1>
- 每一個標簽都可以接收屬性
const element = <div tabIndex="0">注意觀察屬性</div>
const element = <div tabIndex={0}>注意觀察屬性</div>
const element = <div tabIndex={num}>接收變量</div>
JSX默認支持所有html標簽,并且支持所有html標簽?zāi)J的屬性造挽。不過需要注意的是碱璃,為了與創(chuàng)建類的關(guān)鍵字class
區(qū)分開弄痹,html標簽的class屬性在JSX中使用className
代替。
const element = <div className="index">Hello world.</div>
- 作為返回結(jié)果
在引入了React
的模塊中嵌器,我們可以自定一個返回JSX模板的函數(shù)肛真,也可以讓JSX參與到條件判斷中。
import React from 'react';
...
function getResult(type) {
if(type === 'React') {
return <div>React</div>
} else {
return <div>React Native</div>
}
}
當我們需要自定義組件時爽航,這種場景會用得非常多蚓让,往往我們都需要根據(jù)傳入的不同狀態(tài)值動態(tài)的判斷哪些是我們需要的。
- 使用
[].map
暫時列表數(shù)據(jù)
當我們想要渲染一列數(shù)據(jù)時讥珍,可以借助數(shù)組中的map
方法历极。
const data = [1, 2, 3, 4, 5, 6, 7];
<div className="wrapper">
{data.map((item, i) => (
<div className="num" key={i}>{item}</div>
))}
</div>
實踐中,我們有的時候總會逼不得已需要在JSX中處理許多邏輯代碼衷佃,這個時候就必須要將邏輯代碼放入{}
中來處理执解。
const condition = true;
<div className="wrapper">
{condition && <div>hello</div>}
</div>
但是如果使用不善,會導(dǎo)致JSX的可讀性變得非常低纲酗,因此如果大家在使用過程中發(fā)現(xiàn)JSX變得越來越亂越來越復(fù)雜衰腌,則建議有意識的去尋找優(yōu)化方法,不斷的提高自己React的使用水平觅赊。
JSX的本質(zhì)
是js對象
對于一個我們非常屬性的html標簽div
右蕊,我們可以用一個JSON對象去描述它。
const div = {
// 名字
name: 'div',
// 屬性
props: { className: 'wrapper', tabIndex: 0, ... }
// 父節(jié)點
parentNode: h1<Object>,
// 子節(jié)點
children: [div<Object>, span<Object>],
...
}
這里的屬性我就隨意命名吮螺,大概表達意思饶囚。我們也可以通過瀏覽器的開發(fā)者工具將一個標簽打印出來觀察,也會發(fā)現(xiàn)每一個標簽其實也是一個對象鸠补。那樣我們會有更加直觀的感受萝风。
因此,模板語言JSX本質(zhì)上是一個JS對象的語法糖紫岩,這樣能夠更加方便我們使用规惰,React同樣也提供了如圖類似的方式來創(chuàng)建一個JSX標簽。
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
// Note: this structure is simplified
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
也正因為如此泉蝌,我們可以將JSX的標簽對象一一映射到html的標簽對象中歇万。React就是借助這樣的方式,幫助我們將JSX渲染到html的文檔中勋陪。
虛擬DOM
正是因為JSX模板與html模板具有極為相似的特性贪磺,React可以借助這樣的特性將JSX渲染到html中。但同時JSX與html又是不同的東西诅愚,因此我們可以簡單粗暴的理解JSX就是虛擬DOM(render方法的執(zhí)行結(jié)果)
寒锚。
- 為什么要使用虛擬DOM
DOM操作是一件成本很高的事情。
如果你曾經(jīng)有過頁面性能優(yōu)化的經(jīng)驗,一定會非常認可上面這句話刹前。對于瀏覽器而言泳赋,每一次DOM操作都伴隨著大量的計算,也正因為這樣腮郊,當頁面需要的操作不斷變得復(fù)雜摹蘑,每一次操作需要改動的元素變得更多時筹燕,瀏覽器的壓力也會越來越大轧飞。
大家可以在開發(fā)者工具中找到Rendering
,勾選Paint flashing
撒踪,這樣就可以觀察一個頁面中元素的變動过咬。瀏覽器會自動將被重繪的元素高亮顯示出來。
如果你還沒有了解過重繪回流的概念制妄,那么說明你需要去補充一下基礎(chǔ)知識了掸绞,這里不做深入講解。
那么虛擬DOM是如何幫助瀏覽器解決這個問題的呢耕捞?
正常情況下衔掸,我們操作是直接改動html元素。每一次操作都會給瀏覽器增加更多的壓力俺抽。
而虛擬DOM可以幫我們收集短時間來的多次改動敞映,匯總成為一次改動。這樣對于瀏覽器來說磷斧,壓力就減少了很多振愿。如圖。
這就是虛擬DOM的批處理能力弛饭。當然冕末,計算的壓力同樣存在,但是因為虛擬DOM是JS計算的侣颂,因此這樣的方式將本來屬于瀏覽器的壓力讓JS來抗档桃,而我們知道,JS的抗壓能力是比瀏覽器優(yōu)秀很多的憔晒。
除了批處理能力胳蛮,React中虛擬DOM的diff算法也是一大亮點,不過因為是初學(xué)階段丛晌,這里不做深入講解仅炊,也不建議大家太早的關(guān)注更深層次的知識。如果有興趣的同學(xué)可以參考 https://zhuanlan.zhihu.com/p/20346379澎蛛。
講個題外話抚垄。
最近發(fā)現(xiàn)了一個非常有意思的事情。
一個小哥在某個群里問React到底比jQuery好在哪?可能很多人都會覺得這真的是一個很傻的問題呆馁,然而這個Java開發(fā)的小哥哥確實從心底認為jquery很好用桐经,反而React學(xué)習(xí)成本很高,也用的不太舒服浙滤,所以它的好處到底在哪里阴挣,為什么大家都不用easyUI了?
本來這是一件很小的事情纺腊,但是突然想到之前也遇到一個類似的事情畔咧,一個組里的小伙伴很疑惑為什么我們要用async/await
?我試圖解釋了半天他也理解不了這個東西到底好在哪里揖膜。
同樣的事情還發(fā)生在我自己身上誓沸,為什么我們還要去費勁心思去學(xué)typescript
?JS不是很好用嘛壹粟,干嘛要去學(xué)一個超集拜隧?當初ts剛出來的時候名聲大噪,也動手去嘗試了它的語法趁仙,真的感覺很麻煩洪添,用起來加那么多限制條件,鼓搗了一下午也沒覺得typescript到底好在哪里雀费。于是放棄干奢。正是因為認知的原因,傻乎乎的錯過了好久typescript坐儿,直到3.0出來了律胀,才在機緣巧合之下驚喜的發(fā)現(xiàn)哇靠,typescript簡直就是神器貌矿,這才深深的感受到自己真的錯過了太多炭菌。
最近我特別留意了蠻多正在學(xué)習(xí)React的同學(xué),或者已經(jīng)學(xué)了很長時間甚至已經(jīng)在工作中使用React的同學(xué)逛漫,發(fā)現(xiàn)很多人并沒有發(fā)現(xiàn)React到底好在哪里黑低。而大家關(guān)注的重點往往是,某個功能用React應(yīng)該怎么實現(xiàn)酌毡,而不是React這樣實現(xiàn)克握,好在哪里 ~,往往大家學(xué)習(xí)React的起因也不是因為已經(jīng)感受到了React帶來的好處才去學(xué)的枷踏。這樣不同的認知與不同的學(xué)習(xí)源動力菩暗,自然會導(dǎo)致截然不同的學(xué)習(xí)效果。就連學(xué)習(xí)效率也會天差地別旭蠕。
正如我之前說過的停团,工作經(jīng)驗豐富<非工作年限>的開發(fā)人員更能夠直接的體會到新東西(React/Typescript)等的優(yōu)勢旷坦,因為經(jīng)歷過前端開發(fā)刀耕火種的年代,自然就明白模塊化組件化虛擬DOM等概念的重要意義佑稠,也就更容易把這些知識看得更加重要秒梅,視若珍寶。而初學(xué)者直接上來就接觸這些概念舌胶,就常常只會把他們當成一個普通的知識點去學(xué)捆蜀,然后遺忘,所以同樣的東西在不同的人眼中就不一樣幔嫂。
so, 經(jīng)驗豐富的前端開發(fā)者也不會有想要去嘲諷jQuery怎么這么難用辆它,因為我們確確實實經(jīng)過了一些事情,那個年代jQuery就是神器婉烟,盡管現(xiàn)階段jquery已經(jīng)慢慢被棄用娩井,但是它在整個前端發(fā)展歷程中的意義仍然無法替代暇屋。所以如果我們在技術(shù)群里偶爾看到某個程序員用著React/vue嘲諷jQuery的時候似袁,就憑這一點就可以知道這個人一定資歷尚淺,強行裝逼咐刨。
對于新手來說昙衅,要怎么去感受到React的好,我也沒有什么切實可行的辦法定鸟,只是告訴大家有這樣的一個現(xiàn)象而涉,因為我自己也深陷其中,也許到了某個階段联予,自然就明悟了也說不定啼县,我只能在文章里告訴大家這個東西很重要,但是總歸沒有自己切身體會來得深刻沸久,畢竟搞得全文都是重點最終給人的感覺也只是全文都不是重點季眷,所以學(xué)習(xí)這種東西,看努力卷胯,不過要走在行業(yè)前列子刮,更看天賦,看領(lǐng)悟窑睁,看運氣挺峡。大抵如此。