React初識(shí)

React是一個(gè)JavaScript語(yǔ)言的工具庫(kù)奢赂,起源于Facebook的一個(gè)內(nèi)部項(xiàng)目,最初用來(lái)構(gòu)建Instagram的網(wǎng)站呛哟,并于2013年5月開源苞俘。

安裝

對(duì)于React初學(xué)者而言,React官方提供了一個(gè)工具——create-react-app计维,目的是將開發(fā)者人員從配置中解放出來(lái)袜香,從而能快速的進(jìn)入到React應(yīng)用的開發(fā)中。

具體安裝過(guò)程如下:


npm install -g create-react-app ? 全局安裝 creat-react-app 命令

create-react-app ? my-app ? ? ? ? ?使用命令在當(dāng)前目錄下創(chuàng)建一個(gè)名為my-app的react應(yīng)用

cd my-app ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 進(jìn)入my-app項(xiàng)目文件夾

npm-start ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 執(zhí)行該命令


之后會(huì)啟動(dòng)一個(gè)開發(fā)者模式的服務(wù)器鲫惶,同時(shí)瀏覽器自動(dòng)打開一個(gè)網(wǎng)頁(yè)蜈首,指向http://localhost:3000/

界面如下圖所示:

http://localhost:3000/

第一個(gè)React應(yīng)用就這樣誕生了~

生成的文件夾目錄結(jié)構(gòu),如下圖所示:


項(xiàng)目目錄結(jié)構(gòu)

開發(fā)過(guò)程中欠母,我們主要關(guān)注src目錄中的內(nèi)容欢策,而我們所創(chuàng)建項(xiàng)目的入口便是src/index.js文件,這里面的代碼做了這樣一件事赏淌,它渲染了一個(gè)名為App的組件踩寇,將其掛在到了id為root的DOM節(jié)點(diǎn)上。

src/index.js

同時(shí)我們?cè)賮?lái)看看在src/App.js中六水,App組件是怎樣創(chuàng)建的:

src/App.js

可以看到代碼的第一行我們從react庫(kù)中引入了React和Component俺孙,Component作為所有組件的基類辣卒,提供了很多組件共有的功能,之后創(chuàng)建了一個(gè)名為App的組件類睛榄,然后通過(guò)export default App將其導(dǎo)出荣茫,并在在src/index.js中通過(guò)import導(dǎo)入,最后加以使用场靴。

UI=render(data)

React的理念歸結(jié)為一個(gè)公式:UI=render(data)

用戶看到的UI界面啡莉,是一個(gè)函數(shù)——render的執(zhí)行結(jié)果,只接受數(shù)據(jù)——data作為參數(shù)憎乙。這是一個(gè)純函數(shù)票罐,即輸出只依賴于輸入的函數(shù),兩次函數(shù)的調(diào)用如果輸入相同泞边,那么輸出也絕對(duì)相同该押。如此一來(lái),最終的用戶界面阵谚,在render函數(shù)確定的情況下完全取決于輸入數(shù)據(jù)蚕礼。

因此對(duì)于開發(fā)者而言,重要的是區(qū)分梢什,哪些是render奠蹬,哪些是data,想要改變UI嗡午,要做的就是更新data

——《深入淺出React和Redux》

Virtual DOM

在上一節(jié)中囤躁,我們似乎很容易得出這樣一個(gè)結(jié)論,每次更新UI界面荔睹,react都要進(jìn)行重新渲染狸演,這樣會(huì)不會(huì)使得效率低下呢?

事實(shí)上并不會(huì)這樣僻他,React利用Virtual DOM讓每次渲染都只渲染最少的DOM元素宵距。Virtual DOM是對(duì)DOM樹的抽象,它并不觸及瀏覽器部分吨拗,只是存在于JavaScript空間的樹形結(jié)構(gòu)满哪,每次在渲染React組件,React會(huì)對(duì)前后兩次產(chǎn)生的Virtual DOM進(jìn)行比較劝篷,最后只有發(fā)生了改變的地方會(huì)被重新渲染哨鸭。

總而言之,React利用函數(shù)式編程的思維來(lái)解決用戶界面渲染的問(wèn)題携龟,強(qiáng)制所有組件都以數(shù)據(jù)驅(qū)動(dòng)渲染的模式進(jìn)行開發(fā)兔跌。

JSX

要學(xué)習(xí)react首先就要了解JSX,它是JavaScript的一種擴(kuò)展語(yǔ)法峡蟋,使我們能夠在JavaScript中編寫類似HTML的代碼坟桅。

JSX 的基本語(yǔ)法規(guī)則:遇到 HTML 標(biāo)簽(以<開頭),就用 HTML 規(guī)則解析蕊蝗;遇到代碼塊(以{開頭)仅乓,就用 JavaScript 規(guī)則解析。

我們可以用{}將任意的JavaScript表達(dá)式嵌入到JSX中蓬戚。

JSX注釋也很簡(jiǎn)單夸楣,一般用花括號(hào)包圍:


{/* 這里是注釋 */}


React組件

React允許將代碼封裝成組件,然后像插入普通HTML標(biāo)簽?zāi)菢幼愉觯迦胧褂梦覀冏远x的組件豫喧。自定義的組件要以大寫字母開頭,這樣才能被識(shí)別為React組件幢泼。

組件也可以在標(biāo)簽中插入任意屬性紧显,特別注意:

class屬性需要寫成className,for屬性需要寫成htmlFor缕棵,這是因?yàn)閏lass和for是 JavaScript 的保留字孵班。對(duì)于屬性的訪問(wèn),可以通過(guò)this.props.xxx來(lái)訪問(wèn)對(duì)應(yīng)的xxx屬性招驴。

每個(gè)組件必須有一個(gè)render方法篙程,用于輸出組件自身,同時(shí)輸出的組件只能包含一個(gè)頂層標(biāo)簽别厘。

舉個(gè)例子:

名為Demo的組件

在上面的例子中虱饿,我們創(chuàng)建了一個(gè)名為Demo的React組件,用來(lái)在界面輸出Hello触趴,my name is xxx的信息氮发。而this.props.name就是對(duì)組件調(diào)用時(shí)傳入的name屬性的訪問(wèn)。最終界面輸出如下圖所示:

輸出結(jié)果

props & state

React組件的數(shù)據(jù)分為兩種——props和state雕蔽。其中props是組件的對(duì)外接口折柠,state則是組件的內(nèi)部狀態(tài)。它們?nèi)魏我粋€(gè)的改變都會(huì)引發(fā)組件的重新渲染批狐。

props

props是從外部傳遞給組件的數(shù)據(jù)扇售,在上一節(jié)的例子中,name就是傳遞給Demo組件的一個(gè)外部props嚣艇,同時(shí)在組件內(nèi)部承冰,通過(guò)this.props.nam訪問(wèn),這樣我們就能很輕易的將外部的數(shù)據(jù)傳遞給組件內(nèi)部食零。那相反困乒,如果我們想要把內(nèi)部的數(shù)據(jù)傳遞給外部該怎么辦呢?

同樣也是使用props贰谣,因?yàn)閜rops的類型不限于純數(shù)據(jù)娜搂,它還可以是函數(shù)迁霎,所以我們可以定義一個(gè)函數(shù)類型的props,相當(dāng)于父組件交給了自組件一個(gè)回調(diào)函數(shù)百宇。自組件在適當(dāng)?shù)臅r(shí)候調(diào)用這個(gè)函數(shù)考廉,并傳入必要的參數(shù),父組件接收到參數(shù)后携御,對(duì)參數(shù)進(jìn)行相應(yīng)的邏輯處理昌粤。

舉個(gè)例子:

Parent父組件

在Parent父組件中,我們定義了一個(gè)changeResult的函數(shù)啄刹,它接收一個(gè)參數(shù)涮坐,最后計(jì)算出參數(shù)的二次冪,將結(jié)果result顯示在界面中誓军。同時(shí)袱讹,接收的這個(gè)參數(shù)是來(lái)自于Child組件,父組件在調(diào)用子組件時(shí)谭企,將changeValue這個(gè)方法作為子組件的props傳給了子組件廓译。

Child子組件

在Child子組件中,點(diǎn)擊button會(huì)使得子組件中value值加1债查,并在此時(shí)調(diào)用this.props.changeValue非区,將新的value值傳給父組件Parent。

最終的效果如下圖所示:

初始值
點(diǎn)擊button后的值

protoType可以用來(lái)規(guī)范組件的接口盹廷,定義自己可以接收哪些類型或者符合哪些規(guī)則的prop征绸。以上面的Child組件來(lái)說(shuō),我們要求它接收的changeReault是一個(gè)函數(shù):


Child.propTypes = {

changeResult: PropTypes.func

};


上面的代碼要求changeResult這個(gè)prop必須是個(gè)函數(shù)的類型俄占。


state

state代表組件的內(nèi)部狀態(tài)管怠,因?yàn)榻M件不能修改傳入的props,所以為了記錄自身的狀態(tài)變化就得用到state缸榄。

組件的state通常在組件的構(gòu)造函數(shù)中初始化渤弛,且state必須是一個(gè)對(duì)象。


constructor(props){

? ? super(props);

? ? this.state = {

? ? ? ? value: 0

? ? }

}


React還提供了一個(gè)defaultProps功能甚带,用來(lái)制定默認(rèn)的prop值她肯,在特定的props值不是必須且沒(méi)有被傳入的情況下,會(huì)使用這個(gè)指定的默認(rèn)值鹰贵。


Child.defaultProps = {

? ? changeResult: f => f ? ? ?//默認(rèn)是一個(gè)什么都不做的函數(shù)

}


對(duì)state的修改不能直接通過(guò)this.state.xxx來(lái)修改晴氨,需要調(diào)用this.setState({xxx: newValue});來(lái)修改。因?yàn)閠his.setState會(huì)驅(qū)動(dòng)組件進(jìn)行重新渲染碉输,而如果直接用this.state.xxx來(lái)修改籽前,并不能觸發(fā)。

React組件的生命周期

React定義了組件的生命周期,可分為一下三個(gè)過(guò)程:


裝載過(guò)程:Mount —— 組件第一次在DOM樹中渲染的過(guò)程

更新過(guò)程:Update —— 組件被重新渲染的過(guò)程

卸載過(guò)程:Unmount —— 組件從DOM中刪除的過(guò)程


在不同的生命周期中枝哄,React會(huì)一次調(diào)用組件的一些函數(shù)肄梨,這些函數(shù)被稱為生命周期函數(shù)。

裝載過(guò)程

當(dāng)組件第一次被掛載的時(shí)候會(huì)依次調(diào)用以下函數(shù):


constructor

componentWillMount

render

componentDidMount


這幾個(gè)函數(shù)從函數(shù)名就大概知道是什么了膘格。

constructor構(gòu)造函數(shù)峭范,非必需财松,無(wú)狀態(tài)組件可以不使用瘪贱。在存在的情況下,constructor是生命周期中被調(diào)用的第一個(gè)函數(shù)辆毡,在這里我們可以初始化state菜秦,同時(shí)綁定成員函數(shù)的this環(huán)境。

componentWillMount舶掖,非必需球昨,render函數(shù)之前被調(diào)用,與componentDidMount對(duì)稱眨攘。同時(shí)componentWillMount可以在服務(wù)端和瀏覽器端被調(diào)用主慰。

render,必須鲫售,它是React組件中最重要的函數(shù)共螺,它返回一個(gè)JSX描述的結(jié)構(gòu),之后React來(lái)操作渲染過(guò)程情竹,render函數(shù)是一個(gè)純函數(shù)藐不,完全根據(jù)this.state和this.props 來(lái)決定返回結(jié)果,因此在render函數(shù)中調(diào)用this.setState是錯(cuò)誤的秦效。

componentDidMount雏蛮,非必需,只能在瀏覽器端被調(diào)用阱州,componentDidMount函數(shù)并不是緊跟render函數(shù)后面被調(diào)用挑秉,它被調(diào)用時(shí),render函數(shù)返回的東西已經(jīng)引發(fā)來(lái)渲染苔货,組件已經(jīng)被“裝載”到了DOM樹上犀概,此時(shí)可以放心的獲取渲染出來(lái)的任何DOM,也可以通過(guò)ajax獲取數(shù)據(jù)來(lái)填充組件的內(nèi)容蒲赂。

更新過(guò)程

更新過(guò)程會(huì)調(diào)用如下生命周期函數(shù):


componentWillReceiveProps

shouldComponentUpdate

componentWillUpdate

render

componentDidUpdate


但并不是所有更新過(guò)程都會(huì)調(diào)用以上所有函數(shù)阱冶。

我們先來(lái)看看哪些情況會(huì)觸發(fā)更新過(guò)程(默認(rèn)shouldComponentUpdate返回true)

1. 父組件的render函數(shù)被調(diào)用

2. this.setState調(diào)用,但不是每調(diào)用一次就更新一次滥嘴,有時(shí)react會(huì)合并操作木蹬,并最后一次性調(diào)用render更新

3. this.forceUpdate強(qiáng)制更新

而在這些情況下會(huì)依次調(diào)用的生命周期函數(shù),如下圖所示:

更新路徑

componentWillReceiveProps當(dāng)父組件調(diào)用render時(shí)會(huì)觸發(fā),而不是僅僅只有props發(fā)生改變時(shí)才觸發(fā)镊叁。

shouldComponentUpdate默認(rèn)返回true尘颓,如果返回false則立即停止更新,如果恰當(dāng)使用shouldComponentUpdate來(lái)控制是否繼續(xù)更新晦譬,可以有效提高效率疤苹。

componentWillUpdate,當(dāng)shouldComponentUpdate返回true敛腌,緊接著調(diào)用componentWillUpdate卧土,之后是render,再之后是componentDidUpdate像樊。

注意:通過(guò)this.setState函數(shù)引發(fā)的更新尤莺,并不是立刻改變state的值,其實(shí)生棍,在調(diào)用shouldComponentUpdate時(shí)state的值依然是this.setState執(zhí)行之前的值颤霎。

卸載過(guò)程

componentWillUnmount,當(dāng)react組件需要從DOM樹上刪除掉之前會(huì)調(diào)用它涂滴,所以這個(gè)函數(shù)適合做一些清理工作友酱。比如,在componentDidMount中用非react的方法創(chuàng)造了一些DOM元素柔纵,如果撒手不管的話會(huì)造成內(nèi)存泄漏缔杉,那就需要在componentWillUnmount中將這些DOM卸載掉。

參考文章和書籍

http://www.reibang.com/p/4784216b8194

《深入淺出React和Redux》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末首量,一起剝皮案震驚了整個(gè)濱河市壮吩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌加缘,老刑警劉巖鸭叙,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拣宏,居然都是意外死亡沈贝,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門勋乾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宋下,“玉大人,你說(shuō)我怎么就攤上這事辑莫⊙纾” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵各吨,是天一觀的道長(zhǎng)枝笨。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么横浑? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任剔桨,我火速辦了婚禮,結(jié)果婚禮上徙融,老公的妹妹穿的比我還像新娘洒缀。我一直安慰自己,他們只是感情好欺冀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布树绩。 她就那樣靜靜地躺著,像睡著了一般脚猾。 火紅的嫁衣襯著肌膚如雪葱峡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天龙助,我揣著相機(jī)與錄音,去河邊找鬼蛛芥。 笑死提鸟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仅淑。 我是一名探鬼主播称勋,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼涯竟!你這毒婦竟也來(lái)了赡鲜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤庐船,失蹤者是張志新(化名)和其女友劉穎银酬,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筐钟,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡揩瞪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了篓冲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片李破。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖壹将,靈堂內(nèi)的尸體忽然破棺而出嗤攻,到底是詐尸還是另有隱情,我是刑警寧澤诽俯,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布妇菱,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏恶耽。R本人自食惡果不足惜密任,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望偷俭。 院中可真熱鬧浪讳,春花似錦、人聲如沸涌萤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)负溪。三九已至透揣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間川抡,已是汗流浹背辐真。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留崖堤,地道東北人侍咱。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像密幔,于是被迫代替她去往敵國(guó)和親楔脯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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

  • 原教程內(nèi)容詳見(jiàn)精益 React 學(xué)習(xí)指南胯甩,這只是我在學(xué)習(xí)過(guò)程中的一些閱讀筆記昧廷,個(gè)人覺(jué)得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,839評(píng)論 1 18
  • 深入JSX date:20170412筆記原文其實(shí)JSX是React.createElement(componen...
    gaoer1938閱讀 8,070評(píng)論 2 35
  • 做React需要會(huì)什么? react的功能其實(shí)很單一镜廉,主要負(fù)責(zé)渲染的功能弄诲,現(xiàn)有的框架,比如angular是一個(gè)大而...
    蒼都閱讀 14,760評(píng)論 1 139
  • 體驗(yàn)入:早晨聽到同事們說(shuō)了一句“再傳遞負(fù)能量就上報(bào)組織”娇唯,雖然聽著是玩笑話但是說(shuō)明大家都在用心的學(xué)習(xí)了 找核心:學(xué)...
    Tracy_zhang閱讀 183評(píng)論 0 3
  • 這只是只言片語(yǔ)齐遵, 哪能道得出來(lái), 螢火蟲在夜空起舞塔插, 夜鶯卻停止了啼叫梗摇, 那遠(yuǎn)逝的身影, 眼角的淚想许, 是為你的送行...
    愛(ài)吃肉的和尚閱讀 177評(píng)論 0 1