React-JSX核心語(yǔ)法

?1.認(rèn)識(shí)JSX

1.1JSX是什么?

JSX是一種JavaScript的語(yǔ)法擴(kuò)展(eXtension),也在很多地方稱之為JavaScript XML,因?yàn)榭雌鹁褪且欢蝀ML語(yǔ)法;

它用于描述我們的UI界面,并且其完成可以和JavaScript融合在一起使用;

它不同于Vue中的模塊語(yǔ)法,你不需要專門(mén)學(xué)習(xí)模塊語(yǔ)法中的一些指令(比如v-for、v-if、v-else、v-bind);

1.2?為什么React選擇了JSX?

React認(rèn)為渲染邏輯本質(zhì)上與其他UI邏輯存在內(nèi)在耦合

比如UI需要綁定事件(button、a原生等等);

比如UI中需要展示數(shù)據(jù)狀態(tài),在某些狀態(tài)發(fā)生改變時(shí),又需要改變UI;

他們之間是密不可分,所以React沒(méi)有將標(biāo)記分離到不同的文件中,而是將它們組合到了一起,這個(gè)地方就是組件(Component);

當(dāng)然,后面我們還是會(huì)繼續(xù)學(xué)習(xí)更多組件相關(guān)的東西;

在這里,我們只需要知道,JSX其實(shí)是嵌入到JavaScript中的一種結(jié)構(gòu)語(yǔ)法;

2.jsx事件監(jiān)聽(tīng)

2.1通過(guò)onClick直接綁定函數(shù)(方式一)

????通過(guò)直接綁定的方式可以調(diào)用‘btnClick’函數(shù),但是會(huì)有一個(gè)弊端,無(wú)法通過(guò)this調(diào)用組件內(nèi)的狀態(tài)屬性。原因是onClick是通過(guò)React內(nèi)部調(diào)用,沒(méi)有綁定this,所以‘btnClick’函數(shù)內(nèi)的this指向‘undefine’。

直接綁定

2.2 通過(guò)顯示綁定方式調(diào)用(方式二)????

通過(guò)bind函數(shù)主動(dòng)綁定this可以解決btnClick內(nèi)部this指向問(wèn)題,但是方式二的弊端是有大量的重復(fù)代碼,必須需要調(diào)用this.XXX.bind(this),并且傳參也不方便。

顯示綁定this

2.3使用 ES6 class fields 語(yǔ)法(方式三)

你會(huì)發(fā)現(xiàn)我這里將btnClick的定義變成了一種賦值語(yǔ)句:

這是ES6中給類定義屬性的方法,稱之為class fields語(yǔ)法;

因?yàn)檫@里我們賦值時(shí),使用了箭頭函數(shù),所以在當(dāng)前函數(shù)中的this會(huì)去上一個(gè)作用域中查找;

而上一個(gè)作用域中的this就是當(dāng)前的對(duì)象;

箭頭函數(shù)調(diào)用

2.4?事件監(jiān)聽(tīng)時(shí)傳入箭頭函數(shù)(推薦)

因?yàn)?onClick?中要求我們傳入一個(gè)函數(shù),那么我們可以直接定義一個(gè)箭頭函數(shù)傳入:

傳入的箭頭函數(shù)的函數(shù)體是我們需要執(zhí)行的代碼,我們直接執(zhí)行?this.btnClick();

this.btnClick()中通過(guò)this來(lái)指定會(huì)進(jìn)行隱式綁定,最終this也是正確的;


事件監(jiān)聽(tīng)時(shí)傳入箭頭函數(shù)

3.JSX轉(zhuǎn)換本質(zhì)

實(shí)際上,jsx 僅僅只是?React.createElement(component, props, ...children)?函數(shù)的語(yǔ)法糖。

所有的jsx最終都會(huì)被轉(zhuǎn)換成React.createElement的函數(shù)調(diào)用。

React.createElement在源碼的什么位置呢?


React.createElement源碼

createElement需要傳遞三個(gè)參數(shù):

參數(shù)一:type

當(dāng)前ReactElement的類型;

如果是標(biāo)簽元素,那么就使用字符串表示 “div”;

如果是組件元素,那么就直接使用組件的名稱;

參數(shù)二:config

所有jsx中的屬性都在config中以對(duì)象的屬性和值的形式存儲(chǔ)

參數(shù)三:children

存放在標(biāo)簽中的內(nèi)容,以children數(shù)組的方式進(jìn)行存儲(chǔ);

當(dāng)然,如果是多個(gè)元素呢?React內(nèi)部有對(duì)它們進(jìn)行處理,處理的源碼在下方

對(duì)children進(jìn)行的處理:

從第二個(gè)參數(shù)開(kāi)始,將其他所有的參數(shù),放到props對(duì)象的children中


參數(shù)三:children的合并原理

4. 虛擬DOM

我們通過(guò)?React.createElement?最終創(chuàng)建出來(lái)一個(gè) ReactElement對(duì)象:


這個(gè)ReactElement對(duì)象是什么作用呢?React為什么要?jiǎng)?chuàng)建它呢?

原因是React利用ReactElement對(duì)象組成了一個(gè)JavaScript的對(duì)象樹(shù);

JavaScript的對(duì)象樹(shù)就是大名鼎鼎的虛擬DOM(Virtual DOM);

如何查看ReactElement的樹(shù)結(jié)構(gòu)呢?

我們可以將之前的jsx返回結(jié)果進(jìn)行打印;

注意下面代碼中我打jsx的打??;


打印結(jié)果,在瀏覽器中查看:


而ReactElement最終形成的樹(shù)結(jié)構(gòu)就是Virtual DOM。

3.1為什么采用虛擬DOM

為什么要采用虛擬DOM,而不是直接修改真實(shí)的DOM呢?

很難跟蹤狀態(tài)發(fā)生的改變:原有的開(kāi)發(fā)模式,我們很難跟蹤到狀態(tài)發(fā)生的改變,不方便針對(duì)我們應(yīng)用程序進(jìn)行調(diào)試;

操作真實(shí)DOM性能較低:傳統(tǒng)的開(kāi)發(fā)模式會(huì)進(jìn)行頻繁的DOM操作,而這一的做法性能非常的低;

主要原因:DOM操作性能非常低:

首先,document.createElement本身創(chuàng)建出來(lái)的就是一個(gè)非常復(fù)雜的對(duì)象;

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createElement

其次,DOM操作會(huì)引起瀏覽器的回流和重繪,所以在開(kāi)發(fā)中應(yīng)該避免頻繁的DOM操作;

虛擬DOM幫助我們從命令式編程轉(zhuǎn)到了聲明式編程的模式

React官方的說(shuō)法:Virtual DOM 是一種編程理念。

在這個(gè)理念中,UI以一種理想化或者說(shuō)虛擬化的方式保存在內(nèi)存中,并且它是一個(gè)相對(duì)簡(jiǎn)單的JavaScript對(duì)象,我們可以通過(guò)ReactDOM.render讓?虛擬DOM?和?真實(shí)DOM同步起來(lái),這個(gè)過(guò)程中叫做協(xié)調(diào)(Reconciliation);

這種編程的方式賦予了React聲明式的API:你只需要告訴React希望讓UI是什么狀態(tài),React來(lái)確保DOM和這些狀態(tài)是匹配的。

你不需要直接進(jìn)行DOM操作,只可以從手動(dòng)更改DOM、屬性操作、事件處理中解放出來(lái);

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容