JSX 知識(shí)準(zhǔn)備
JSX 并不是一門(mén)全新的語(yǔ)言及刻,僅僅是一個(gè)語(yǔ)法糖,允許開(kāi)發(fā)者在javascript中編寫(xiě)XML語(yǔ)言穷当。這樣使用JavaScript來(lái)構(gòu)建組件以及組件之間關(guān)系的應(yīng)用,在代碼層面顯得更加清晰淹禾,而不再是使用JavaScript操作DOM來(lái)創(chuàng)建組件以及組件之間的嵌套關(guān)系馁菜。
作為是React的核心部分,JSX使用XML標(biāo)記的方式直接聲明頁(yè)面铃岔。在JavaScript代碼里直接寫(xiě)XML的語(yǔ)法汪疮,每一個(gè)XML標(biāo)簽都會(huì)被JSX轉(zhuǎn)換工具轉(zhuǎn)換成純JavaScript代碼盾似。HTML直接寫(xiě)到JavaScript中不加任何分號(hào)砚哗,這就是JSX的語(yǔ)法奧義
JSX環(huán)境準(zhǔn)備
JSX必須借助ReactJS環(huán)境才能運(yùn)行厘托。在編寫(xiě)JSX代碼之前就珠,需要先加載ReactJS文件狈蚤,比react.js.光有ReactJs還不行剩晴,還需要加載JSX解析器萤晴。下面大家一起準(zhǔn)備好一個(gè)最基礎(chǔ)的ReactJS環(huán)境
創(chuàng)建一個(gè)test.html文件
-
在
<head>
標(biāo)簽中引入如下文件<script src="http://cdn.bootcss.com/react/15.2.0/react.js"></script> <script src="http://cdn.bootcss.com/react/15.2.0/react-dom.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
這樣環(huán)境就搭建好了互艾,然后按照慣例载碌,雙手奉上一個(gè)Hello World 程序猜嘱。
<body>
<div id="example"></div>
<script type="text/babel">
var HelloComponent = React.createClass({
render: function(){
return <span>Hello World !</span>
}
});
ReactDOM.render(
<HelloComponent />,
document.getElementById('example')
);
</script>
</body>
運(yùn)行結(jié)果
如上面代碼,我們?cè)贘avaScript中書(shū)寫(xiě)HTML標(biāo)簽時(shí)嫁艇,不再像以前那樣作為字符串用引號(hào)引起來(lái)朗伶,而是想在XML文件中書(shū)寫(xiě)一樣,直接寫(xiě)即可步咪。
除了<span>Hello World !</span>
這種直接使用的HTML標(biāo)簽外论皆,還有一個(gè)<HelloComponent />
標(biāo)簽。這個(gè)是ReactJS創(chuàng)建的組件類(lèi)標(biāo)簽,通過(guò)這種方式点晴,把創(chuàng)建的HelloComponent組件引用進(jìn)來(lái)感凤。ReactJS約定,自定義的組件標(biāo)簽首字母一定要大些觉鼻,用來(lái)區(qū)分是組件標(biāo)簽還是HTML標(biāo)簽俊扭。
注意幾點(diǎn)
- script 標(biāo)簽的 type 屬性為 text/babel,這是React 獨(dú)有的 JSX 語(yǔ)法坠陈,跟 JavaScript 不兼容萨惑。凡是在頁(yè)面中直接使用 JSX 的地方,都要加上 type="text/babel"仇矾。
- 一共用了三個(gè)庫(kù): react.js 庸蔼、react-dom.js 和 browser.min.js ,它們必須首先加載贮匕。其中姐仅,react.js 是 React 的核心庫(kù),react-dom.js 是提供與 DOM 相關(guān)的功能刻盐, browser.min.js的作用是將 JSX 語(yǔ)法轉(zhuǎn)為 JavaScript 語(yǔ)法掏膏。
- 將 JSX 語(yǔ)法轉(zhuǎn)為 JavaScript 語(yǔ)法,這一步很消耗時(shí)間《匦浚現(xiàn)在前端項(xiàng)目馒疹,都會(huì)使用前端工程化,不會(huì)直接在html頁(yè)面中直接寫(xiě)js代碼乙墙,寫(xiě)好的js代碼都會(huì)使用工具進(jìn)行編譯壓縮等颖变。這樣的話,我們的jsx也會(huì)通過(guò)編譯直接轉(zhuǎn)化成js語(yǔ)法听想,讓瀏覽器直接使用腥刹。
JSX執(zhí)行JavaScript表達(dá)式
JSX使用{}來(lái)執(zhí)行JavaScript表達(dá)式。
var arr = [
<h1>Hello world!</h1>,
<h2>React is awesome</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
JSX定義屬性&&樣式使用
HTML中可以通過(guò)標(biāo)簽上的屬性來(lái)改變當(dāng)前元素的樣式汉买,當(dāng)然衔峰,這在JSX中也是可以的,只不過(guò)JSX在使用行內(nèi)樣式的時(shí)候是有缺陷的蛙粘。朽色。使用{{}}而不是引號(hào)的方式,如下
React.render(
<div style={{color:'red',marginTop:'20px'}}>
xxxxx
</div>,
document.body
);
注:直接在標(biāo)簽上使用style屬性時(shí)组题,要寫(xiě)成style={{}}是兩個(gè)大括號(hào)葫男,外層大括號(hào)是告知jsx這里是js語(yǔ)法,和真實(shí)DOM不同的是崔列,屬性值不能是字符串而必須為對(duì)象梢褐,需要注意的是屬性名同樣需要駝峰命名法旺遮。即margin-top要寫(xiě)成marginTop,屬性之間以逗號(hào)間隔盈咳。還有class 屬性需要寫(xiě)成 className 耿眉,for 屬性需要寫(xiě)成 htmlFor ,這是因?yàn)?class 和 for 是 JavaScript 的保留字鱼响。
JSX中的延展屬性
在JSX中我們可以使用ES6中的最新語(yǔ)法...
來(lái)遍歷對(duì)象
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello {this.props.name} get {this.props.votes} votes</h1>;
}
});
var Lucy = {
name: "feng",
votes: "23"
}
ReactDOM.render(
<HelloMessage {...Lucy} />,
document.getElementById('example')
);
JSX中的事件綁定
JSX支持事件的綁定鸣剪,語(yǔ)法類(lèi)似于HTML中事件的綁定,不同的是這里事件的名稱(chēng)必須按照駝峰式丈积,下面給個(gè)例子大家參考一下筐骇。
var HelloComponent = React.createClass({
testClick: function (str) {
alert('hello ' + str)
},
render: function() {
return (
<p
onClick={this.testClick.bind(this, 'feng')} style={{olor:'#ff6600',width:'200px', height:'100p'}}
>
Click me
</p>
)
}
})
ReactDOM.render(
<HelloComponent />,
document.getElementById('example')
);
知曉了JSX的基本使用之后,開(kāi)始介紹ReactJS的組件的概念和使用方法
組件初步
ReactJS的基礎(chǔ)就是實(shí)例化江滨,即按功能封裝成一個(gè)又一個(gè)的組件铛纬,各個(gè)組件維護(hù)自己的狀態(tài)和UI,當(dāng)狀態(tài)改變時(shí)唬滑,會(huì)自動(dòng)重新渲染整個(gè)組件告唆,多個(gè)組件一起協(xié)作構(gòu)成了整個(gè)ReactJS應(yīng)用。
以一個(gè)簡(jiǎn)單的Hello World開(kāi)始
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="http://cdn.bootcss.com/react/15.2.0/react.js"></script>
<script src="http://cdn.bootcss.com/react/15.2.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
<head>
<body>
<div id="example"></div>
<script type="text/babel">
var HelloMessage = React.createClass({
render: function() {
return <div>Hello,{this.props.name}</div>
}
})
ReactDOM.render(<HelloMessage name="World" />, document.getElementById('example'))
</script>
</body>
運(yùn)行結(jié)果:
審查元素發(fā)現(xiàn)DOM結(jié)構(gòu)如下:
上面的代碼中晶密,我們調(diào)用React提供的工廠方法來(lái)創(chuàng)建組件擒悬,其中:
- React是全局對(duì)象,ReactJS的所有頂級(jí)API都掛在這個(gè)對(duì)象下稻艰。
- React.createClass是ReactJS用來(lái)創(chuàng)建組件類(lèi)的方法懂牧,這個(gè)對(duì)象必須包含一個(gè)render方法和若干可選的生命周期(詳情請(qǐng)見(jiàn)下文)方法,其中
- render是一個(gè)組件級(jí)的API,是React.createClass內(nèi)部最常用的API,該方法主要用來(lái)返回組件結(jié)構(gòu)
- React.render(這里我用的是ReactDOM.render)是最常用的方法连锯,用于將模板轉(zhuǎn)換成HTML語(yǔ)言归苍,并將轉(zhuǎn)換后的DOM結(jié)構(gòu)插入到制定的DOM節(jié)點(diǎn)上
- 簡(jiǎn)而言之就是:先通過(guò)React.createClass來(lái)創(chuàng)建一個(gè)組件類(lèi)用狱,調(diào)用組件的render方法輸出組件的DOM結(jié)構(gòu)运怖,最后調(diào)用React.render將組建插入到id為example的節(jié)點(diǎn)上
這里我們需要保證render函數(shù)是純函數(shù):即同樣的輸入始終返回相同的輸出,并且執(zhí)行過(guò)程中沒(méi)有副作用(和DOM交互或者發(fā)Ajax請(qǐng)求)夏伊。但一個(gè)組件要和DOM交互或者發(fā)Ajax請(qǐng)求需求是很正常的摇展,那么就要用到其他生命周期方法了。
組件的狀態(tài)與屬性
組件本質(zhì)上是狀態(tài)機(jī)溺忧,輸入確定咏连,輸出一定確定。組件把狀態(tài)與結(jié)果一一對(duì)應(yīng)起來(lái)鲁森,組件中有state與prop(狀態(tài)與屬性)祟滴。
- 屬性(props)是由父組件傳遞給子組件的;
- 狀態(tài)(state)是子組件內(nèi)部維護(hù)的數(shù)據(jù)歌溉,當(dāng)狀態(tài)發(fā)生變化的同時(shí)垄懂,組件也會(huì)進(jìn)行更新骑晶。當(dāng)狀態(tài)發(fā)生轉(zhuǎn)換時(shí)會(huì)觸發(fā)不同的鉤子函數(shù)(詳見(jiàn)下文中生命周期),從而讓開(kāi)發(fā)者有機(jī)會(huì)做出相應(yīng)草慧。
props屬性的用法
props是一個(gè)對(duì)象桶蛔,是組建用來(lái)接收外面?zhèn)鱽?lái)的參數(shù),組件內(nèi)部是不允許修改自己的props屬性的漫谷,只能夠通過(guò)父組件來(lái)修改仔雷。具體的使用方法如下
-
接收鍵值對(duì)數(shù)據(jù)
<HelloWorld name= ? />
字符串:"XiaoFeng"
求值表達(dá)式 {123}、{"XiaoFeng"}
數(shù)組{[1,2,3]}
變量{variable}
-
函數(shù)求值表達(dá)式{function}(不推薦舔示,如果需要函數(shù)可以單獨(dú)把函數(shù)提取出來(lái)然后單獨(dú)調(diào)用函數(shù))
var HelloWorld =React.createClass({ render:function () { console.log(this.props) return <p>Hello,{this.props.name ? this.props.name : " World"}</p>; }, }); var HelloUniverse = React.createClass({ getInitialState:function () { return { name:'' }; }, handleChange: function (event) { this.setState({name: event.target.value}); }, render: function () { return (<div> <HelloWorld name={this.state.name}></HelloWorld> <br/> <input type="text" onChange={this.handleChange} /> </div> ); } }); ReactDOM.render(<HelloUniverse />,example);
-
setProps
已過(guò)時(shí)碟婆,即將廢棄
-
propTypes
組件的屬性可以接受任意值,字符串斩郎、對(duì)象脑融、函數(shù)等等都可以。有時(shí)缩宜,我們需要一種機(jī)制肘迎,驗(yàn)證別人使用組件時(shí),提供的參數(shù)是否符合要求锻煌。
var MyTitle = React.createClass({ propTypes: { title: React.PropTypes.string.isRequired, }, render: function() { return <h1> {this.props.title} </h1>; } });
上面的Mytitle組件有一個(gè)title屬性妓布。PropTypes 告訴 React,這個(gè) title 屬性是必須的宋梧,而且它的值必須是字符串∠徽樱現(xiàn)在,我們?cè)O(shè)置 title 屬性的值是一個(gè)數(shù)值捂龄。
var data = 123; ReactDOM.render( <MyTitle title={data} />, document.body );
這樣一來(lái)释涛,title屬性就通不過(guò)驗(yàn)證了【氩祝控制臺(tái)會(huì)顯示一行錯(cuò)誤信息
-
getDefaultProps
getDefaultProps 方法可以用來(lái)設(shè)置組件屬性的默認(rèn)值
var MyTitle = React.createClass({ getDefaultProps : function () { return { title : 'Hello World' }; }, render: function() { return <h1> {this.props.title} </h1>; } }); ReactDOM.render(<MyTitle />,document.body);
-
this.props.children
this.props 對(duì)象的屬性與組件的屬性一一對(duì)應(yīng)唇撬,但是有一個(gè)例外,就是 this.props.children 屬性展融。它表示組件的所有子節(jié)點(diǎn)
var NotesList = React.createClass({ render: function() { return ( <ol> { React.Children.map(this.props.children, function (child) { return <li>{child}</li>; }) } </ol> ); } }); ReactDOM.render( <NotesList> <span>hello</span> <span>world</span> </NotesList>,example );
上面代碼的 NoteList 組件有兩個(gè) span 子節(jié)點(diǎn)窖认,它們都可以通過(guò) this.props.children 讀取。這里需要注意告希, this.props.children 的值有三種可能:
- 如果當(dāng)前組件沒(méi)有子節(jié)點(diǎn)扑浸,它就是 undefined;
- 如果有一個(gè)子節(jié)點(diǎn)燕偶,數(shù)據(jù)類(lèi)型是 object喝噪;
- 如果有多個(gè)子節(jié)點(diǎn),數(shù)據(jù)類(lèi)型就是 array
React 提供一個(gè)工具方法 React.Children 來(lái)處理 this.props.children 指么。我們可以用 React.Children.map 來(lái)遍歷子節(jié)點(diǎn)酝惧,而不用擔(dān)心 this.props.children 的數(shù)據(jù)類(lèi)型是 undefined 還是 object驰吓。
state屬性的用法
React把組件當(dāng)成狀態(tài)機(jī),一旦用戶(hù)交互導(dǎo)致?tīng)顟B(tài)發(fā)生變化系奉,就會(huì)觸發(fā)重新渲染UI檬贰。this.state會(huì)隨著用戶(hù)的交互而發(fā)生變化。
-
工作原理
常用的通知 React 數(shù)據(jù)變化的方法是調(diào)用 setState(data, callback)缺亮。這個(gè)方法會(huì)合并(merge) data 到 this.state翁涤,并重新渲染組件。渲染完成后萌踱,調(diào)用可選的 callback 回調(diào)葵礼。大部分情況下不需要提供 callback,因?yàn)?React 會(huì)負(fù)責(zé)把界面更新到最新?tīng)顟B(tài)并鸵。
-
getInitialState
object getInitialState()
getInitialState 方法用于定義初始狀態(tài)鸳粉,也就是一個(gè)對(duì)象,這個(gè)對(duì)象可以通過(guò) this.state 屬性讀取园担。在組件掛載之前調(diào)用一次届谈。返回值將會(huì)作為 this.state 的初始值。
-
setState
setState(object nextState[, function callback])
this.setState 方法用于修改狀態(tài)值弯汰,每次修改以后艰山,自動(dòng)調(diào)用 this.render 方法,再次渲染組件咏闪。
注意:
- 絕對(duì)不要直接改變 this.state曙搬,因?yàn)樵谥笳{(diào)用 setState() 可能會(huì)替換掉你做的更改。把 this.state 當(dāng)做不可變的鸽嫂。
- setState()不會(huì)立刻改變 this.state纵装,而是創(chuàng)建一個(gè)即將處理的state轉(zhuǎn)變。在調(diào)用該方法之后獲取 this.state 的值可能會(huì)得到現(xiàn)有的值据某,而不是最新設(shè)置的值橡娄。
- 不保證 setState()調(diào)用的同步性,為了提升性能哗脖,可能會(huì)批量執(zhí)行state轉(zhuǎn)變和DOM 渲染瀑踢。
- setState ( ) 將總是觸發(fā)一次重繪扳还,除非在 shouldComponentUpdate()中實(shí)現(xiàn)了條件渲染邏輯才避。如果使用可變的對(duì)象,但是又不能在shouldComponentUpdate()中實(shí)現(xiàn)這種邏輯氨距,僅在新 state 和之前的 state 存在差異的時(shí)候調(diào)用 setState()可以避免不必要的重新渲染桑逝。
常用的模式是創(chuàng)建多個(gè)只負(fù)責(zé)渲染數(shù)據(jù)的無(wú)狀態(tài)(stateless)組件,在它們的上層創(chuàng)建一個(gè)有狀態(tài)(stateful)組件并把它的狀態(tài)通過(guò) props 傳給子級(jí)俏让。這個(gè)有狀態(tài)的組件封裝了所有用戶(hù)的交互邏輯楞遏,而這些無(wú)狀態(tài)組件則負(fù)責(zé)聲明式地渲染數(shù)據(jù)茬暇。
組件的生命周期
生命周期各階段
在整個(gè)ReactJS的聲明周期中,主要會(huì)經(jīng)歷這四個(gè)階段:創(chuàng)建階段寡喝、實(shí)例化階段糙俗、更新階段、銷(xiāo)毀階段预鬓。下面通過(guò)一段代碼巧骚,來(lái)深入了解組件各個(gè)環(huán)節(jié)的運(yùn)作流程
var OneComponent = React.createClass({
//1.創(chuàng)建階段
getDefaultProps: function() {
//在創(chuàng)建類(lèi)的時(shí)候被調(diào)用
console.log('getDefaultProps');
return {}
},
//2.實(shí)例化階段
getInitialState: function() {
//獲取this.state的默認(rèn)值
console.log('getInitialState');
return {};
},
componentWillMount: function() {
//在render之前調(diào)用此方法
//業(yè)務(wù)邏輯的處理都應(yīng)該放在這里,比如對(duì)state的操作等
console.log('componentWillMount')
},
render: function() {
//渲染并返回一個(gè)虛擬DOM
console.log('render');
return (
<div> hello <b> {this.props.name} </b></div>
)
},
componentDidMount: function() {
//該方法發(fā)生在render方法之后
//在該方法中格二,ReactJS會(huì)使用render方法返回的虛擬DOM對(duì)象來(lái)創(chuàng)建真實(shí)DOM結(jié)構(gòu)
console.log('componentDidMount');
},
//3.個(gè)更新階段
componentWillReceieveProps: function() {
//該方法發(fā)生在this.props被修改或富組件調(diào)用setProps()方法之后
console.log('componentWillRecieveProps');
},
shouldComponentUpdate: function() {
//是否需要更新
console.log('shouldComponentUpdate');
return true;
},
componentWillUpadate: function() {
//將要更新
console.log('componentWillUpadate');
},
componentDidUpdate: function() {
//更新完畢
console.log('componentDidUpdate');
},
//4.銷(xiāo)毀階段
componentWillUnmout: function() {
//銷(xiāo)毀時(shí)被調(diào)用
console.log('componentWillUnmout');
}
})
ReactDOM.render(
<OneComponent name="World "/>,
document.getElementById('example')
);
創(chuàng)建階段:
該階段主要發(fā)生在創(chuàng)建組件類(lèi)的時(shí)候劈彪,即在調(diào)用React.createClass的時(shí)候。這個(gè)階段只會(huì)觸發(fā)一個(gè)getDefaultProps方法顶猜,該方法會(huì)返回一個(gè)對(duì)象沧奴,并緩存下來(lái)。然后與富組件制定的props對(duì)象合并长窄,最后賦值給this.props作為該組件的默認(rèn)屬性滔吠。
實(shí)例化階段
該階段主要發(fā)生在實(shí)例化組件類(lèi)的時(shí)候,也就是組件類(lèi)被調(diào)用的時(shí)候挠日。
ReactDOM.render(
<OneComponent name="World "/>,
document.getElementById('example')
);
該組件被調(diào)用的時(shí)候屠凶,這個(gè)階段會(huì)觸發(fā)一系列的流程,具體的執(zhí)行順序如下所示肆资。
getInitialState矗愧。初始化組件的state的值,其返回值會(huì)賦值給組件的this.state屬性郑原。
-
componentWillMount 在渲染(掛載)之前調(diào)用一次唉韭。
此時(shí)this.refs對(duì)象為空。如果在此時(shí)調(diào)用this.setState()則會(huì)更新this.state對(duì)象犯犁,而render只會(huì)調(diào)用一次属愤。
render 根據(jù)state的值,生成頁(yè)面需要的虛擬DOM結(jié)構(gòu)酸役,并返回該結(jié)構(gòu)
-
componentDidMount 在渲染之后調(diào)用一次住诸。根據(jù)虛擬DOM結(jié)構(gòu)而生成的真實(shí)DOM進(jìn)行相應(yīng)的處理,組件內(nèi)部可以通過(guò)this.getDOMNode()來(lái)獲取當(dāng)前組件的節(jié)點(diǎn)涣澡,然后就可以像在web開(kāi)發(fā)中那樣操作里面的DOM元素了贱呐。
componentDidMount () { const textbox = React.findDOMNode(this.refs.text) if (this.props.autoFocus) textbox.focus() }
更新階段
主要發(fā)生在用戶(hù)操作或者組件有更新的時(shí)候,此時(shí)會(huì)根據(jù)用戶(hù)的操作行為進(jìn)行相應(yīng)的頁(yè)面結(jié)構(gòu)的調(diào)整入桂。該階段也會(huì)觸發(fā)一系列的流程奄薇,具體的執(zhí)行順序如下所示。
-
componentWillReceiveProps 在將要接收props時(shí)調(diào)用抗愁。在該函數(shù)中馁蒂,通澈峭恚可以調(diào)用this.setState方法來(lái)完成對(duì)state的修改。
props是父組件傳遞給資組建的沫屡。父組件發(fā)生render的時(shí)候子組件就會(huì)調(diào)用componentWillReceiveProps(不管props有沒(méi)有更新饵隙,也不管父子組件之間有沒(méi)有數(shù)據(jù)交換)。
componentWillReceiveProps (nextProps) { if (this.props.disabled !== nextProps.disabled) { // disabled這個(gè)屬性改變了 } }
-
shouldComponentUpdate:該方法用來(lái)攔截新的props或state沮脖,然后根據(jù)事先設(shè)定好的判斷邏輯癞季,返回值決定組件是否需要update。
組件掛載之后倘潜,每次調(diào)用setState后都會(huì)調(diào)用shouldComponentUpdate判斷是否需要重新渲染組件绷柒。默認(rèn)返回true,需要重新render涮因。在比較復(fù)雜的應(yīng)用里废睦,有一些數(shù)據(jù)的改變并不影響界面展示,可以在這里做判斷养泡,優(yōu)化渲染效率嗜湃。
shouldComponentUpdate (nextProps, nextState) { // 比較props或者states,返回true則更新照常澜掩,返回false則取消更新购披,且不會(huì)調(diào)用下面的兩個(gè)生命周期函數(shù) }
componentWillUpdate :組件更新之前調(diào)用一次。當(dāng)上一部中shouldComponentUpdate方法返回true時(shí)候肩榕,就可以在該方法中做一些更新之前的操作刚陡。
render 根據(jù)一系列的diff算法,聲稱(chēng)需要更心動(dòng)額虛擬DOM數(shù)據(jù)株汉。實(shí)際表明筐乳,在render中,最好只做數(shù)據(jù)和模板的結(jié)合乔妈,而不進(jìn)行state等邏輯的修改蝙云,這樣組件結(jié)構(gòu)更清晰。
-
componentDidUpdate 組件的更新已經(jīng)同步到DOM中后出發(fā)路召。
除了首次render之后調(diào)用componentDidMount勃刨,其它render結(jié)束之后都是調(diào)用componentDidUpdate。
銷(xiāo)毀階段
- componentWillUnmount 會(huì)在組件即將從掛載點(diǎn)移去時(shí)調(diào)用股淡,用來(lái)取出去除即將被銷(xiāo)毀的DOM節(jié)點(diǎn)的引用身隐,或者是清除計(jì)時(shí)器,取消監(jiān)聽(tīng)的時(shí)間等等揣非。
注意:
絕對(duì)不要在componentWillUpdate和componentDidUpdate中調(diào)用this.setState方法抡医,否則將導(dǎo)致無(wú)限循環(huán)調(diào)用躲因。
componentWillMount早敬、componentDidMount和componentWillUpdate忌傻、componentDidUpdate可以對(duì)應(yīng)起來(lái)。區(qū)別在于搞监,前者只有在掛載的時(shí)候會(huì)被調(diào)用水孩;而后者在以后的每次更新渲染之后都會(huì)被調(diào)用。
組件生命周期流程圖
組件之間的通信
先創(chuàng)建一個(gè)父類(lèi)組件Parent琐驴,它內(nèi)部調(diào)用一個(gè)叫做Child的子組件俘种,并將接收到的外部參數(shù)name傳遞給子組件Child。
var Parent = React.createClass({
handleClick: function() {
this.refs.myTextInput.focus();
},
render: function() {
return (
<div onClick={this.handleClick}>
<input type="text" ref="myTextInput" />
Parent is:
<Child name={this.props.name}></Child>
</div>
)
}
});
在創(chuàng)建一個(gè)子類(lèi)組件Child
var Child = React.createClass({
render: function() {
return <span>{this.props.name}</span>
}
});
自后通過(guò)React.render方法將組件渲染到頁(yè)面上
ReactDOM.render(
<Parent name="React" />,document.getElementById('example')
);
運(yùn)行結(jié)果
整個(gè)應(yīng)用的功能是父組件接收傳入的用戶(hù)名稱(chēng)绝淡,并將用于名稱(chēng)傳給子組件宙刘,最后再由子組件渲染顯示到頁(yè)面上。這些組件直接按是怎么通訊的呢牢酵?下面通過(guò)兩方面介紹一下
- 子組件調(diào)用父組件的方法悬包。從上面的例子可以看出,子組件要拿到父組件的屬性撑瞧,需要通過(guò)this.props方法曼尊。所以料滥,如果子組件想要調(diào)用父組件的方法屿岂,只需要父組件把要被調(diào)用的方法以屬性的方式放在子組件上阻肩,子組件內(nèi)部便可通過(guò)"this.props.被調(diào)用的方法"這樣的方式拿到name屬性的。然后渡贾,每次父組件修改了傳入的name屬性囤屹,子組件便會(huì)得到通知复局,然后自動(dòng)獲取新的name屬性
- 父組件調(diào)用子組件的方法角钩。子組件調(diào)用父組件是通過(guò)prop屬性脊髓,而反過(guò)來(lái)依疼,父組件調(diào)用子組件通過(guò)的就是 ref 屬性。子組件被設(shè)置了ref屬性之后,父組件便可以通過(guò)this.ref.xxx來(lái)獲取到子組件了盒蟆,其中xx為子組件的ref值寒屯。
組件實(shí)踐
1. 靜態(tài)組件
var MyComponent=React.createClass({
render: function() {
return <h1 className="my-h1" style={{color:'red'}}>Hello world!</h1>;
}
});
ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);
運(yùn)行結(jié)果
2. 動(dòng)態(tài)組件
var Counter = React.createClass({
incrementCount: function(){
this.setState({
count: this.state.count + 1
});
},
getInitialState: function(){
return {
count: 0
}
},
render: function(){
return (
<div className="my-component">
<h1>Count: {this.state.count}</h1>
<button type="button" onClick={this.incrementCount}>{this.props.name}</button>
</div>
);
}
});
ReactDOM.render(
<Counter name="遞增按鈕" />,
document.getElementById('mount-point')
);
運(yùn)行結(jié)果:
參考內(nèi)容
- React入門(mén)實(shí)例教程
- React Native入門(mén)與實(shí)踐
- React 生命周期小結(jié)