React進階(七)模板語言JSX與虛擬DOM

夢 想

我們想要創(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)每一個標簽其實也是一個對象鸠补。那樣我們會有更加直觀的感受萝风。

html中的div元素

因此,模板語言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撒踪,這樣就可以觀察一個頁面中元素的變動过咬。瀏覽器會自動將被重繪的元素高亮顯示出來。

image.png

如果你還沒有了解過重繪回流的概念制妄,那么說明你需要去補充一下基礎(chǔ)知識了掸绞,這里不做深入講解。

那么虛擬DOM是如何幫助瀏覽器解決這個問題的呢耕捞?

正常情況下衔掸,我們操作是直接改動html元素。每一次操作都會給瀏覽器增加更多的壓力俺抽。
而虛擬DOM可以幫我們收集短時間來的多次改動敞映,匯總成為一次改動。這樣對于瀏覽器來說磷斧,壓力就減少了很多振愿。如圖。

image.png

這就是虛擬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)悟窑睁,看運氣挺峡。大抵如此。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末担钮,一起剝皮案震驚了整個濱河市橱赠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箫津,老刑警劉巖狭姨,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吓著,死亡現(xiàn)場離奇詭異,居然都是意外死亡送挑,警方通過查閱死者的電腦和手機绑莺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惕耕,“玉大人纺裁,你說我怎么就攤上這事∷九欤” “怎么了欺缘?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長挤安。 經(jīng)常有香客問我谚殊,道長,這世上最難降的妖魔是什么蛤铜? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任嫩絮,我火速辦了婚禮,結(jié)果婚禮上围肥,老公的妹妹穿的比我還像新娘剿干。我一直安慰自己,他們只是感情好穆刻,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布置尔。 她就那樣靜靜地躺著,像睡著了一般氢伟。 火紅的嫁衣襯著肌膚如雪榜轿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天朵锣,我揣著相機與錄音谬盐,去河邊找鬼。 笑死猪勇,一個胖子當著我的面吹牛设褐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泣刹,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼助析,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了椅您?” 一聲冷哼從身側(cè)響起外冀,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掀泳,沒想到半個月后雪隧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體西轩,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年脑沿,在試婚紗的時候發(fā)現(xiàn)自己被綠了藕畔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡庄拇,死狀恐怖注服,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情措近,我是刑警寧澤溶弟,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站瞭郑,受9級特大地震影響辜御,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屈张,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一擒权、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袜茧,春花似錦菜拓、人聲如沸瓣窄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俺夕。三九已至裳凸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間劝贸,已是汗流浹背姨谷。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留映九,地道東北人梦湘。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像件甥,于是被迫代替她去往敵國和親捌议。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容