React入門實例教程

現(xiàn)在最熱門的前端框架垛孔,毫無疑問是React激挪。在基于React的React Native發(fā)布一天之內(nèi),就獲得了 5000 顆星番刊,受矚目程度可見一斑。

React 起源于 Facebook 的內(nèi)部項目影锈,因為該公司對市場上所有JavaScript MVC 框架芹务,都不滿意,就決定自己寫一套鸭廷,用來架設(shè) Instagram 的網(wǎng)站枣抱。做出來以后,發(fā)現(xiàn)這套東西很好用辆床,就在2013年5月開源了佳晶。

由于 React 的設(shè)計思想極其獨特,屬于革命性創(chuàng)新讼载,性能出眾轿秧,代碼邏輯卻非常簡單。所以咨堤,越來越多的人開始關(guān)注和使用菇篡,認為它可能是將來 Web 開發(fā)的主流工具。

這個項目本身也越滾越大一喘,從最早的UI引擎變成了一整套前后端通吃的 Web App 解決方案驱还。衍生的 React Native 項目,目標更是宏偉凸克,希望用寫 Web App 的方式去寫 Native App铝侵。如果能夠?qū)崿F(xiàn),整個互聯(lián)網(wǎng)行業(yè)都會被顛覆触徐,因為同一組人只需要寫一次 UI 咪鲜,就能同時運行在服務(wù)器、瀏覽器和手機(參見《也許撞鹉,DOM 不是答案》)疟丙。

既然 React 這么熱門,看上去充滿希望鸟雏,當然應(yīng)該好好學(xué)一下享郊。從技術(shù)角度,可以滿足好奇心孝鹊,提高技術(shù)水平炊琉;從職業(yè)角度,有利于求職和晉升,有利于參與潛力大的項目苔咪。但是锰悼,好的 React 教程卻不容易找到,這一方面因為這項技術(shù)太新团赏,剛剛開始走紅箕般,大家都沒有經(jīng)驗,還在摸索之中舔清;另一方面因為 React 本身還在不斷變動丝里,API 一直在調(diào)整,至今沒發(fā)布1.0版体谒。

我學(xué)習(xí) React 時杯聚,就很苦惱。有的教程討論一些細節(jié)問題抒痒,對入門沒幫助械媒;有的教程寫得不錯,但比較短评汰,無助于看清全貌纷捞。我斷斷續(xù)續(xù)學(xué)了幾個月,看過二十幾篇教程被去,在這個過程中主儡,將對自己有幫助的 Demo 都收集下來,做成了一個庫React Demos惨缆。

下面糜值,我就根據(jù)這個庫,寫一篇全面又易懂的 React 入門教程坯墨。你只需要跟著每一個Demo做一遍寂汇,就能初步掌握React 。當然捣染,前提是你必須擁有基本JavaScript和DOM知識骄瓣,但是你讀完就會發(fā)現(xiàn),React所要求的預(yù)備知識真的很少耍攘。

零榕栏、安裝

React 的安裝包,可以到官網(wǎng)下載蕾各。不過扒磁,React Demos已經(jīng)自帶 React 源碼,不用另外安裝式曲,只需把這個庫拷貝到你的硬盤就行了妨托。

1

$ git clone git@github.com:ruanyf/react-demos.git

如果你沒安裝 git, 那就直接下載zip壓縮包

下面要講解的10個例子在各個 Demo 子目錄兰伤,每個目錄都有一個 index.html 文件内颗,在瀏覽器打開這個文件(大多數(shù)情況下雙擊即可),就能立刻看到效果医清。

需要說明的是,React 可以在瀏覽器運行卖氨,也可以在服務(wù)器運行会烙,但是本教程只涉及瀏覽器。一方面是為了盡量保持簡單筒捺,另一方面 React 的語法是一致的柏腻,服務(wù)器的用法與瀏覽器差別不大。Demo11是服務(wù)器首屏渲染的例子系吭,有興趣的朋友可以自己去看源碼五嫂。

一、HTML 模板

使用 React 的網(wǎng)頁源碼肯尺,結(jié)構(gòu)大致如下沃缘。

上面代碼有兩個地方需要注意。首先则吟,最后一個 script 標簽的 type 屬性為 text/jsx 槐臀。這是因為 React 獨有的 JSX 語法,跟 JavaScript 不兼容氓仲。凡是使用 JSX 的地方水慨,都要加上 type="text/jsx" 。

其次敬扛,React 提供兩個庫:react.js和JSXTransformer.js晰洒,它們必須首先加載。其中啥箭,JSXTransformer.js 的作用是將 JSX 語法轉(zhuǎn)為 JavaScript 語法谍珊。這一步很消耗時間,實際上線的時候急侥,應(yīng)該將它放到服務(wù)器完成抬驴。

1

$ jsx src/ build/

上面命令可以將 src 子目錄的 js 文件進行語法轉(zhuǎn)換,轉(zhuǎn)碼后的文件全部放在 build 子目錄缆巧。

二布持、React.render()

React.render 是 React 的最基本方法,用于將模板轉(zhuǎn)為 HTML 語言陕悬,并插入指定的 DOM 節(jié)點题暖。

1

2

3

4React.render(

Hello, world!,

document.getElementById('example')

);

上面代碼將一個 h1 標題,插入 example 節(jié)點(查看demo01),運行結(jié)果如下胧卤。

三唯绍、JSX 語法

上一節(jié)的代碼, HTML 語言直接寫在 JavaScript 語言之中枝誊,不加任何引號况芒,這就是 JSX 的語法,它允許 HTML 與 JavaScript 的混寫(查看Demo02)叶撒。

1

2

3

4

5

6

7

8

9varnames = ['Alice','Emily','Kate'];

React.render(

{

names.map(function(name) {

returnHello, {name}! ? ?})

}

,

document.getElementById('example')

);

上面代碼體現(xiàn)了 JSX 的基本語法規(guī)則:遇到 HTML 標簽(以 < 開頭)绝骚,就用 HTML 規(guī)則解析;遇到代碼塊(以 { 開頭)祠够,就用 JavaScript 規(guī)則解析压汪。上面代碼的運行結(jié)果如下。

JSX 允許直接在模板插入 JavaScript 變量古瓤。如果這個變量是一個數(shù)組止剖,則會展開這個數(shù)組的所有成員(查看demo03)。

1

2

3

4

5

6

7

8vararr = [

Hello world!,

React is awesome,

];

React.render(

{arr},

document.getElementById('example')

);

上面代碼的arr變量是一個數(shù)組落君,結(jié)果 JSX 會把它的所有成員穿香,添加到模板,運行結(jié)果如下绎速。

四扔水、組件

React 允許將代碼封裝成組件(component),然后像插入普通 HTML 標簽一樣朝氓,在網(wǎng)頁中插入這個組件魔市。React.createClass 方法就用于生成一個組件類(查看demo04)。

1

2

3

4

5

6

7

8

9varHelloMessage = React.createClass({

render:function() {

returnHello {this.props.name};

}

});

React.render(

,

document.getElementById('example')

);

上面代碼中赵哲,變量 HelloMessage 就是一個組件類待德。模板插入時,會自動生成 HelloMessage 的一個實例(下文的"組件"都指組件類的實例)枫夺。所有組件類都必須有自己的 render 方法将宪,用于輸出組件。

組件的用法與原生的 HTML 標簽完全一致橡庞,可以任意加入屬性较坛,比如,就是 HelloMessage 組件加入一個 name 屬性扒最,值為 John丑勤。組件的屬性可以在組件類的 this.props 對象上獲取,比如 name 屬性就可以通過 this.props.name 讀取吧趣。上面代碼的運行結(jié)果如下法竞。

添加組件屬性耙厚,有一個地方需要注意,就是 class 屬性需要寫成 className 岔霸,for 屬性需要寫成 htmlFor 薛躬,這是因為 class 和 for 是 JavaScript 的保留字。

五呆细、this.props.children

this.props 對象的屬性與組件的屬性一一對應(yīng)型宝,但是有一個例外,就是 this.props.children 屬性絮爷。它表示組件的所有子節(jié)點(查看demo05)趴酣。

1

2

3

4

5

6

7

8

9

10

11

12

13

14varNotesList = React.createClass({

render:function() {

return(

{

this.props.children.map(function(child) {

return{child} ? ? ? ?})

}

);

}

});

React.render(

hello ? ?world ?,

document.body

);

上面代碼的 NoteList 組件有兩個 span 子節(jié)點,它們都可以通過 this.props.children 讀取略水,運行結(jié)果如下价卤。

這里需要注意劝萤,只有當子節(jié)點多余1個時渊涝,this.props.children 才是一個數(shù)組,否則是不能用 map 方法的床嫌, 會報錯跨释。

六、React.findDOMNode()

組件并不是真實的 DOM 節(jié)點厌处,而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu)沮协,叫做虛擬 DOM (virtual DOM)南片。只有當它插入文檔以后,才會變成真實的 DOM 。根據(jù) React 的設(shè)計突照,所有的 DOM 變動,都先在虛擬 DOM 上發(fā)生殿托,然后再將實際發(fā)生變動的部分支鸡,反映在真實 DOM上,這種算法叫做 DOM diff 椭住,它可以極大提高網(wǎng)頁的性能表現(xiàn)崇渗。

但是,有時需要從組件獲取真實 DOM 的節(jié)點京郑,這時就要用到 React.findDOMNode 方法(查看demo06)宅广。

1

2

3

4

5

6

7

8

9

10

11

12

13varMyComponent = React.createClass({

handleClick:function() {

React.findDOMNode(this.refs.myTextInput).focus();

},

render:function() {

return(

);

}

});

React.render(

,

document.getElementById('example')

);

上面代碼中,組件 MyComponent 的子節(jié)點有一個文本輸入框些举,用于獲取用戶的輸入跟狱。這時就必須獲取真實的 DOM 節(jié)點,虛擬 DOM 是拿不到用戶輸入的户魏。為了做到這一點兽肤,文本輸入框必須有一個 ref 屬性套腹,然后 this.refs.[refName] 就指向這個虛擬 DOM 的子節(jié)點,最后通過 React.findDOMNode 方法獲取真實 DOM 的節(jié)點资铡。

需要注意的是电禀,由于 React.findDOMNode 方法獲取的是真實 DOM ,所以必須等到虛擬 DOM 插入文檔以后笤休,才能使用這個方法尖飞,否則會返回 null 。上面代碼中店雅,通過為組件指定 Click 事件的回調(diào)函數(shù)政基,確保了只有等到真實 DOM 發(fā)生 Click 事件之后,才會調(diào)用 React.findDOMNode 方法闹啦。

React 組件支持很多事件沮明,除了 Click 事件以外,還有 KeyDown 窍奋、Copy荐健、Scroll 等,完整的事件清單請查看官方文檔琳袄。

七江场、this.state

組件免不了要與用戶互動,React 的一大創(chuàng)新窖逗,就是將組件看成是一個狀態(tài)機址否,一開始有一個初始狀態(tài),然后用戶互動碎紊,導(dǎo)致狀態(tài)變化佑附,從而觸發(fā)重新渲染 UI(查看demo07)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18varLikeButton = React.createClass({

getInitialState:function() {

return{liked:false};

},

handleClick:function(event) {

this.setState({liked: !this.state.liked});

},

render:function() {

vartext =this.state.liked ?'like':'haven\\'t liked';

return(

You {text}this. Click to toggle.

);

}

});

React.render(

,

document.getElementById('example')

);

上面代碼是一個 LikeButton 組件仗考,它的 getInitialState 方法用于定義初始狀態(tài)音同,也就是一個對象,這個對象可以通過 this.state 屬性讀取痴鳄。當用戶點擊組件瘟斜,導(dǎo)致狀態(tài)變化,this.setState 方法就修改狀態(tài)值痪寻,每次修改以后螺句,自動調(diào)用 this.render 方法,再次渲染組件橡类。

由于 this.props 和 this.state 都用于描述組件的特性蛇尚,可能會產(chǎn)生混淆。一個簡單的區(qū)分方法是顾画,this.props 表示那些一旦定義取劫,就不再改變的特性匆笤,而 this.state 是會隨著用戶互動而產(chǎn)生變化的特性。

八谱邪、表單

用戶在表單填入的內(nèi)容炮捧,屬于用戶跟組件的互動,所以不能用 this.props 讀鹊胍(查看demo08)咆课。

1

2

3

4

5

6

7

8

9

10

11

12

13

14varInput = React.createClass({

getInitialState:function() {

return{value:'Hello!'};

},

handleChange:function(event) {

this.setState({value: event.target.value});

},

render:function() {

varvalue =this.state.value;

return(

{value} ? ? ? ? ?);

}

});

React.render(, document.body);

上面代碼中,文本輸入框的值扯俱,不能用 this.props.value 讀取书蚪,而要定義一個 onChange 事件的回調(diào)函數(shù),通過 event.target.value 讀取用戶輸入的值迅栅。textarea 元素殊校、select元素、radio元素都屬于這種情況读存,更多介紹請參考官方文檔为流。

九、組件的生命周期

組件的生命周期分成三個狀態(tài):

Mounting:已插入真實 DOM

Updating:正在被重新渲染

Unmounting:已移出真實 DOM

React 為每個狀態(tài)都提供了兩種處理函數(shù)宪萄,will 函數(shù)在進入狀態(tài)之前調(diào)用艺谆,did 函數(shù)在進入狀態(tài)之后調(diào)用榨惰,三種狀態(tài)共計五種處理函數(shù)拜英。

componentWillMount()

componentDidMount()

componentWillUpdate(object nextProps, object nextState)

componentDidUpdate(object prevProps, object prevState)

componentWillUnmount()

此外,React 還提供兩種特殊狀態(tài)的處理函數(shù)琅催。

componentWillReceiveProps(object nextProps):已加載組件收到新的參數(shù)時調(diào)用

shouldComponentUpdate(object nextProps, object nextState):組件判斷是否重新渲染時調(diào)用

這些方法的詳細說明居凶,可以參考官方文檔。下面是一個例子(查看demo09)藤抡。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28varHello = React.createClass({

getInitialState:function() {

return{

opacity: 1.0

};

},

componentDidMount:function() {

this.timer = setInterval(function() {

varopacity =this.state.opacity;

opacity -= .05;

if(opacity < 0.1) {

opacity = 1.0;

}

this.setState({

opacity: opacity

});

}.bind(this), 100);

},

render:function() {

return(

Hello {this.props.name}

);

}

});

React.render(

,

document.body

);

上面代碼在hello組件加載以后侠碧,通過 componentDidMount 方法設(shè)置一個定時器,每隔100毫秒缠黍,就重新設(shè)置組件的透明度弄兜,從而引發(fā)重新渲染。

另外瓷式,組件的style屬性的設(shè)置方式也值得注意替饿,不能寫成

1

style="opacity:{this.state.opacity};"

而要寫成

1

style={{opacity:this.state.opacity}}

這是因為React 組件樣式是一個對象,所以第一重大括號表示這是 JavaScript 語法贸典,第二重大括號表示樣式對象视卢。

十、Ajax

組件的數(shù)據(jù)來源廊驼,通常是通過 Ajax 請求從服務(wù)器獲取据过,可以使用 componentDidMount 方法設(shè)置 Ajax 請求惋砂,等到請求成功,再用 this.setState 方法重新渲染 UI(查看demo10)绳锅。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29varUserGist = React.createClass({

getInitialState:function() {

return{

username:'',

lastGistUrl:''

};

},

componentDidMount:function() {

$.get(this.props.source,function(result) {

varlastGist = result[0];

if(this.isMounted()) {

this.setState({

username: lastGist.owner.login,

lastGistUrl: lastGist.html_url

});

}

}.bind(this));

},

render:function() {

return(

{this.state.username}'s last gist is

here.

);

}

});

React.render(

,

document.body

);

上面代碼使用 jQuery 完成 Ajax 請求西饵,這是為了便于說明。React 沒有任何依賴鳞芙,完全可以使用其他庫罗标。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市积蜻,隨后出現(xiàn)的幾起案子闯割,更是在濱河造成了極大的恐慌,老刑警劉巖竿拆,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宙拉,死亡現(xiàn)場離奇詭異,居然都是意外死亡丙笋,警方通過查閱死者的電腦和手機谢澈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來御板,“玉大人锥忿,你說我怎么就攤上這事〉±撸” “怎么了敬鬓?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長笙各。 經(jīng)常有香客問我钉答,道長,這世上最難降的妖魔是什么杈抢? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任数尿,我火速辦了婚禮,結(jié)果婚禮上惶楼,老公的妹妹穿的比我還像新娘右蹦。我一直安慰自己,他們只是感情好歼捐,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布何陆。 她就那樣靜靜地躺著,像睡著了一般窥岩。 火紅的嫁衣襯著肌膚如雪甲献。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天颂翼,我揣著相機與錄音晃洒,去河邊找鬼慨灭。 笑死,一個胖子當著我的面吹牛球及,可吹牛的內(nèi)容都是我干的氧骤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼吃引,長吁一口氣:“原來是場噩夢啊……” “哼筹陵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起镊尺,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤朦佩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后庐氮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體语稠,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年弄砍,在試婚紗的時候發(fā)現(xiàn)自己被綠了仙畦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡音婶,死狀恐怖慨畸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衣式,我是刑警寧澤寸士,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站瞳收,受9級特大地震影響碉京,放射性物質(zhì)發(fā)生泄漏厢汹。R本人自食惡果不足惜螟深,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烫葬。 院中可真熱鬧界弧,春花似錦、人聲如沸搭综。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兑巾。三九已至条获,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒋歌,已是汗流浹背帅掘。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工委煤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人修档。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓碧绞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吱窝。 傳聞我的和親對象是個殘疾皇子讥邻,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

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

  • 作者:阮一峰原文地址:http://www.ruanyifeng.com/blog/2015/03/react.h...
    IT程序獅閱讀 1,094評論 0 16
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過程中的一些閱讀筆記院峡,個人覺得該教程講解深入淺出兴使,比目前大...
    leonaxiong閱讀 2,843評論 1 18
  • 現(xiàn)在最熱門的前端框架,毫無疑問是 React 照激。上周鲫惶,基于 React 的 React Native 發(fā)布,結(jié)果一...
    sakura_L閱讀 432評論 0 0
  • 按照慣例实抡,先給ReactJS背書 React是一個Facebook開發(fā)的UI庫欠母,于2013年5月開源,并迅速的從最...
    艾倫先生閱讀 3,238評論 1 12
  • GUIDS 第一章 為什么使用React吆寨? React 一個提供了用戶接口的JavaScript庫赏淌。 誕生于Fac...
    jplyue閱讀 3,544評論 1 11