自己最近的項(xiàng)目是基于react的德挣,于是讀了一遍react的文檔平绩,做了一些記錄(除了REFERENCE部分還沒開始讀)
文章也可以直接訪問我的前端網(wǎng)站來查看
quick start
Tutorial
建立一個模塊
我們可以使用React.createClass()來創(chuàng)建一個React模塊圈匆。我們通過一個JS對象傳了一些方法給這個函數(shù),最重要的方法是render捏雌,返回了最終會變成HTML的部分跃赚。
render里面的div不是真正的DOM節(jié)點(diǎn),他們是React的div components的實(shí)例化性湿,不直接產(chǎn)生HTML纬傲,所以XSS保護(hù)是默認(rèn)的。
我們使用ReactDom.render()來實(shí)例化入口框架肤频,這個方法必須在最下面模塊定義好了才執(zhí)行叹括,這個方法來真正的產(chǎn)生DOM,其他的平臺的話有其他的生成方式着裹,比如React Native领猾。
HTML tags在生成的時候會調(diào)用React.createElement(tagName)來創(chuàng)建。
this.props
由父模塊傳遞給子模塊的數(shù)據(jù)骇扇,我們可以在子模塊中通過this.props來訪問得到摔竿。
dangerouslySetInnerHTML
如果我們想要直接插入html進(jìn)入文檔中(這一點(diǎn)需要自己來保證XSS的問題),我們可以使用dangerouslySetInnerHTML這個屬性來添加少孝。
遍歷輸出
var commentListNodes = this.props.comList.map(function(comment){
return (
<Comment author={comment.author} key={comment.id}>
{comment.text}
</Comment>
);
});
我們可以通過map方法來得到數(shù)組继低,然后使用的時候直接{commentListNodes}就能輸出了。
state
目前稍走,依賴于props袁翁,所有的組件都是被刷新了一次,props是不變的婿脸,這個被父組件傳過來的且被父組件擁有粱胜。所以出現(xiàn)了state這個屬性,我們使用這個可變的私有的值來改變狀態(tài)狐树。我們可以使用setState()來rerender這個組件焙压。getInitialState這個方法會在初始化的時候執(zhí)行一次來初始化組件的初始狀態(tài)。
componentDidMount
這個方法會在組件第一次初始化之后被調(diào)用
控制組件的輸入
這里推薦的也是在this.state里面存這個value抑钟,在input的onChange時調(diào)用修改this.setState來改變涯曲。包括submit方法的話就是監(jiān)聽onSubmit。我們可以先調(diào)用e.preventDefault()來阻止默認(rèn)行為在塔。
從子組件傳數(shù)據(jù)給父組件
我們可以在調(diào)用子組件的時候幻件,將callback綁在props上,然后調(diào)用子組件的props上面的方法來調(diào)用父組件相應(yīng)的方法蛔溃。
我們在寫一些回調(diào)的時候要綁定好this
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
this.setState({data: data});
}.bind(this)
});
//就像這樣綁定好this
Tip
這里還給了一個小建議绰沥,我們在添加了某一項(xiàng)之后篱蝇,可以直接加進(jìn)list,如果ajax失敗了再重置回去
Thinking in React
創(chuàng)建react的步驟
我們分解成react要尊崇單一職責(zé)原則揪利,盡量把交互與展示分開态兴,展示也根據(jù)種類分細(xì)點(diǎn)
然后我們先不考慮交互,不考慮傳輸?shù)臄?shù)據(jù)疟位,先創(chuàng)建一個靜態(tài)的項(xiàng)目出來
react是單項(xiàng)綁定的
然后我們要計算出最小的state我們需要什么瞻润,通過父組件傳的,不變的甜刻,能夠通過其他state計算得到的都不應(yīng)該是state
我們需要得出哪一塊需要數(shù)據(jù)绍撞,如果我們實(shí)在沒法區(qū)分的時候,我們可以專門在其上用一個組件來專門管理state
社區(qū)資源
這個就先不看了
Guides
why react
React就像是MVC的view層得院,react主要解決的是大項(xiàng)目數(shù)據(jù)不斷變化的場景傻铣。我們只需要修改數(shù)據(jù),react會幫我們進(jìn)行所有的UI更新祥绞。
他只更新被改變的部分非洲。
Displaying Data
他的組件是很封閉的,所以更容易重用蜕径,更容易測試以及分離相關(guān)两踏。
Components更像是方法,接受props和state來生成HTML兜喻。(react模塊只能生成一個簡單的根節(jié)點(diǎn)梦染,如果想要返回大量的節(jié)點(diǎn)的話,得用一個根節(jié)點(diǎn)包裹起來)
React允許我們用js對象的形式來創(chuàng)建HTML朴皆,如`React.createElement('a',{href:''},'Hello!')帕识。為了簡便,我們還可以使用createFactory的形式來創(chuàng)建遂铡。但是使用比較少肮疗,還是JSX比較方便。
JSX時間上只是一種語法扒接,并不是使用React的必需品伪货,不用的話,就得像上面一樣使用create的形式慢慢創(chuàng)建珠增。
Jsx in Depth
我們在JSX里面使用HTML tag的時候,用小寫的形式砍艾。如果是HTML屬性的話蒂教,使用駝峰的寫法。并且因?yàn)閏lass和for都作為XML的本身的屬性名脆荷,所以我們分別用className和htmlFor來代替凝垛。
我們在版本0.11以上可以使用namespaced components懊悯,就是在某個組件之下進(jìn)行申明。
當(dāng)我們在屬性里想要使用js的表達(dá)式的時候梦皮,用一個大括號包裹起來炭分,替代雙引號。
boolean attribute剑肯,如disable捧毛,readonly,checked让网,required直接省略屬性值和{true}一樣呀忧,如果不寫和值為{false}效果一樣。
js表達(dá)式也可以用來申明生成哪個子節(jié)點(diǎn)溃睹,比如{ifShow ? <Nav/> : <Login/>}而账。
注釋的話使用這種形式是可以的{/* */}。
Jsx 延展屬性
我們可以使用延展屬性因篇,來講一個對象所有的屬性復(fù)制到另一個對象上泞辐。我們可以多次使用,或者和普通的屬性一起用竞滓,不過得注意順序咐吼,后面的會覆蓋前面的。這里是React直接支持虽界。
var props = {foo:"check"}
var component = <Component {...props} foo='name'/>
console.log(component.props.foo);
//name
延展屬性在ES6的效果主要是將數(shù)組類型的一個個推出來汽烦,就像是apply方法一樣,支持情況當(dāng)然不好啦莉御,但是Bebal可以轉(zhuǎn)撇吞。
JSX 一些陷阱
如果想插入·這種符號的話,我們可以直接插入礁叔,但是如果想插入動態(tài)的話牍颈,我們就會以這樣的形式包裝起來{'·'},然后就沒法顯示了
我們可以直接以UTF-8的形式寫個點(diǎn)琅关,或者我們可以寫unicode的編碼\u00b7煮岁,或者我們用個span包起來,例如{['First ', <span>·</span>, ' Second']}
涣易,或者我們可以直接dangerouslySetInnerHTML={{__html: 'First · Second'}}這樣來強(qiáng)行插入原始的HTML画机。
原生的HTML的自定義屬性必須以data開頭,自定義的節(jié)點(diǎn)的屬性可以是任意的新症,aria-hidden這種aria-開頭的屬性是可以正常render的步氏。
交互以及動態(tài)UI
他自動把方法綁定在模塊上,是使用的事件代理徒爹,完全綁在了根元素上荚醒。
模塊就是狀態(tài)機(jī)芋类。
通過setState來將data merge進(jìn)入this.state中,這里的merge只有一層界阁,如果想深層次的merge侯繁,使用那個immutability helpers
所以我們應(yīng)該有許多stateless的模塊來負(fù)責(zé)渲染,然后在其上有一個stateful的模塊來將state通過props傳給這個模塊泡躯。
計算過的數(shù)據(jù)贮竟,react模塊以及與props里面重復(fù)的數(shù)據(jù)都不應(yīng)該在State里面出現(xiàn)。
Multiple Components
動機(jī)主要是將關(guān)注點(diǎn)分離精续。
組件自己沒法修改props坝锰,這樣可以保證組件是始終如一的。Owner負(fù)責(zé)修改以及傳遞狀態(tài)重付。
注意Owner和Parent是不一樣的顷级,<Parent><Child/></Parent>
這個是parent,而owner是React.createClass确垫。我們可以在Parent里面使用this.props.children來操作弓颈。
我們最好不要用hide來隱藏,我們應(yīng)該直接讓他們消失删掀,對于list生成的我們需要給每一個一個唯一的key來保證他們正常且不別破壞翔冀。
數(shù)據(jù)流是單向綁定的。
JS執(zhí)行的速度是非撑幔快的纤子,所以基本上沒有性能瓶頸。主要的瓶頸是DOM的渲染款票,而這點(diǎn)React幫我們通過批處理以及臟檢測來優(yōu)化過了控硼。
當(dāng)我們真的感覺到性能問題的時候,我們可以重寫shouldComponentUpdate來讓他返回false就可以了艾少,但是其實(shí)不是很需要卡乾。
Reusable Components
設(shè)計接口的時候,將那些簡單設(shè)計的元素分解為可重復(fù)使用的缚够,良好設(shè)計的接口幔妨。下次就可以復(fù)用了。
為了保證我們的組件被正確的使用谍椅,我們可以通過設(shè)置propTypes來限制用戶傳入的數(shù)據(jù)误堡,但是這個東西只有在development模式
才會有效。
default prop values
我們可以在用戶沒有傳的時候設(shè)置一個默認(rèn)值雏吭,調(diào)用getDefaultProps就可以設(shè)置默認(rèn)值了锁施,如果用戶設(shè)置過的話,就會被忽略
Transferring Props: A Shortcut
有的時候我們想要從父元素傳遞props給子元素思恐,我們可以直接使用spread syntax來簡寫沾谜,比如直接{...this.props}這樣。
Mixins
當(dāng)不同的組件擁有相同的功能的時候胀莹,我們可以使用mixins基跑,這個就是將組件的功能進(jìn)行抽離的一個方法,還蠻有意思的描焰。使用的時候加個mixins: [SetIntervalMixin]
就可以了媳否。
一個很重要的有點(diǎn)在于,如果有多個Mixin在同一個生命周期的方法執(zhí)行荆秦,那么他們都會被執(zhí)行篱竭,并且會嚴(yán)格按照申明的順序執(zhí)行。
ES6 Classes
我們也可以使用es6的class語法來聲明組件步绸,唯一不同的是沒有g(shù)etInitialState這個方法掺逼,我們只能在constructor里面手動初始化state。
而且方法如果想要在render里面以this來調(diào)用的話瓤介,必須在constructor里面bind一下this吕喘。
還有propTypes和defaultProps得在外面申明,而不是寫在里面刑桑。下面的例子
export class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
this.tick = this.tick.bind(this);
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div onClick={this.tick}>
Clicks: {this.state.count}
</div>
);
}
}
Counter.propTypes = { initialCount: React.PropTypes.number };
Counter.defaultProps = { initialCount: 0 };
關(guān)于this的綁定氯质,我們可以在調(diào)用的時候綁定,也可以使用箭頭祠斧,不過最好像上面一樣在constructor里面綁定闻察,這樣只綁定了一次。
<div onClick={this.tick.bind(this)}>//bad
<div onClick={()=> this.tick()}>//bad
ES6的語法的話沒有Mixins的支持琢锋。
Stateless Functions
如果組件只是一個簡單的js function的話辕漂,我們可以使用這種語法
function HelloMessage(props) {
return <div>Hello {props.name}</div>;
}
//或者直接使用下面的箭頭語法
const HelloMessage = (props) => <div>Hello {props.name}</div>;
這種比較適合沒有l(wèi)ifestyle方法的,不存有內(nèi)部狀態(tài)吩蔑,我們?nèi)匀豢梢栽O(shè)置propTypes和defaultProps钮热。就像ES6的設(shè)置一樣。我們的項(xiàng)目應(yīng)該較多的是stateless的模塊烛芬。
Transferring Props
我們想要傳遞給子模塊的時候加上某個屬性的話隧期,可以直接使用spread語法。<Component {...this.props} more="values" />
如果沒有用jsx的話赘娄,我們可以使用ES6的語法Object.assign和underscore的extends仆潮。
如果我們在某一層組件的時候截斷某個屬性,然后將其他屬性傳下去的話遣臼,可以使用other的語法性置。
function FancyCheckbox(props) {
var { checked, ...other } = props;
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
// `other` contains { onClick: console.log } but not the checked property
return (
<div {...other} className={fancyClass} />
);
}
ReactDOM.render(
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
Hello world!
</FancyCheckbox>,
document.getElementById('example')
);
這樣子的話,other就會只包含除了checked以外的屬性了揍堰,主要是因?yàn)?code>checked這個屬性在html的結(jié)構(gòu)有特殊的意義鹏浅,而在自定義的組件沒有這個效果嗅义。
我們也可以使用rest properties,var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
隐砸,不過在webpack里面得加上transform-object-rest-spread這個plugin之碗。
不用jsx的話,我們可以使用underscore的omit來刪屬性和extends來擴(kuò)展季希。
Forms
與HTML對應(yīng)的褪那,value是被input和textarea支持的。
checked是被input的checkbox和radio支持的式塌。
selected是被options支持的博敬。
注意HTML中,textarea的值是被設(shè)置在兩個標(biāo)簽之間峰尝,REACT是在value屬性上偏窝。
onChange事件會在input和textarea的值發(fā)生改變的時候觸發(fā),還有input的checked改變武学,以及option的selected改變的時候囚枪。
如果我們在render方法里面寫死了input的value,那么我們輸入會被忽視的劳淆,只有value改為state的可變的值才行链沼。
我們可以使用defaultValue給input,textarea沛鸵,select(這個支持multiple)括勺,然后radio和checkbox的值是defaultChecked,注意這個值只能夠在初始化的時候曲掰。
Working with the browser
react快的原因是因?yàn)樗恢苯优cDOM交流疾捍,render方法返回的對DOM的描述,react會計算最快的更新頁面的方法栏妖。
事件系統(tǒng)完美處理乱豆。
當(dāng)我們想要調(diào)用html本身的命令的時候或者接觸真實(shí)的DOM樹,我們可以使用refs來控制吊趾。
Component Lifecycle
模塊有3個主要的階段:
- Mounting:組件準(zhǔn)備插入DOM中
- Updating:組件更新
- Unmounting:組件從DOM中刪除
Mounting提供了getInitialState()和componentWillMount()和componentDidMount()宛裕。
Updating提供了componentWillReceiveProps(這個方法的價值在于組件接收到新的props的時候,我們可以比較新老的props论泛,然后setState揩尸。這個方法在初次mount的時候并不會被觸發(fā),因?yàn)檫@個時候沒有老的props)屁奏,shouldComponentUpdate岩榆,componentWillUpdate(組件即將執(zhí)行更新之前,我們無法執(zhí)行setState方法),componentDidUpdate(更新發(fā)生之后會立即觸發(fā))勇边。
Unmounting提供了componentWillUnmount()在組件被移除之前觸發(fā)犹撒。
Mounted好了的復(fù)合組件也提供了component.forceUpdate()來強(qiáng)行重新刷一次。
react支持IE9以及以上粒褒,但是我們可以引入es5-shim和es5-sham來讓老版的支持油航,這其實(shí)取決于我們自己。
Refs to Components
構(gòu)建組件完了怀浆,你可能想要在render的component實(shí)例上調(diào)用方法。大多數(shù)情況下應(yīng)該是用不到的怕享,因?yàn)檎5臄?shù)據(jù)流應(yīng)該是父組件傳props給子組件的执赡。
jsx并不返回一個component的實(shí)例,他只是返回一個ReactElement(這只是一個告訴React這個組件應(yīng)該是什么樣子的輕量的)函筋。
我們想要調(diào)用某個組價實(shí)例的方法沙合,只能在最上層的component使用(就是ReactDom.render生成的東西)。在組件的內(nèi)部跌帐,我們應(yīng)該自己處理他們之間的狀態(tài)首懈,或者使用另一種方法來得到ref(字符串屬性或者回調(diào)方法屬性)。
The ref Callback Attribute
ref屬性我們可以直接寫成一個回調(diào)方法谨敛。這個方法會在組件結(jié)束mount之后立即被觸發(fā)究履,參數(shù)是引用的組件。我們可以直接使用這個組件或著把他存了等到以后使用脸狸。
這個方法會在componentDidMount之前觸發(fā)最仑。
render: function() {
return (
<TextInput
ref={function(input) {
if (input != null) {
input.focus();
}
}} />
);
},
render: function() {
return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
this._input.focus();
},
當(dāng)我們將refs添加給div的時候,我們得到的是DOM元素炊甲,如果給自定義的組件綁定泥彤,我們得到的是react的實(shí)例。如果是我們自定義的組件卿啡,我們可以調(diào)用任何在他的class里面定義的方法吟吝。
當(dāng)組件unmounted或者ref改變的時候,老的ref都會以null來被調(diào)用颈娜,所以說當(dāng)ref update的時候剑逃,在被組件實(shí)例為參數(shù)之前,會立即調(diào)用一次null為參數(shù)的官辽。(這點(diǎn)需要注意的)
The ref String Attribute
我們也可以簡單的加一個string的ref屬性炕贵,然后我們在其他的事件處理里面就可以this.refs.xx來調(diào)用了。
Tooling Integration
作者希望react成為環(huán)境無關(guān)的野崇,推薦了一些工具來讓我們更好地使用各種種類的語言称开。
Language Tooling
我們寫成JSX的文件的話,我們要用babel先轉(zhuǎn)化為純粹的react的語法。Flow和TypeScrip也都支持JSX了鳖轰。
Package Management
我們可以在commonjs系統(tǒng)browserify或者webpack里面直接npm的形式來引入react和react-dom清酥。
Server-side Environments
react并不是真的依賴于DOM,所以可以后端來執(zhí)行蕴侣,將HTML吐在頁面上焰轻,如果是nodejs的話,是可以ReactDOMServer.rendertoString的昆雀。
如果是java的話辱志,可以依賴于Nashorn這個JS的執(zhí)行器來轉(zhuǎn)化JSX。
Add-ons
這是一些react提供的功能插件狞膘,這些相對于核心來說變化的會比較多一些揩懒。以下的是一些實(shí)驗(yàn)性質(zhì)的:
- TransitionGroup and CSSTransitionGroup:解決那些不容易實(shí)現(xiàn)的動畫,例如在組件移除的時候的動畫挽封。
- LinkedStateMixin:這個是將form的屬性與state綁在一起的插件已球,如果form比較大的話,這個還是很關(guān)鍵的辅愿。
- ...還有很多下面會慢慢介紹的
Animation
react提供了ReactTransitionGroup這種比較級別比較低的api來讓我們使用智亮,還提供了ReactCSSTransitionGroup來讓我們更好的使用css實(shí)現(xiàn)的動畫。包括進(jìn)入和離開頁面的動畫点待。
當(dāng)我們在list添加的時候阔蛉,我們可以使用ReactCSSTransitionGroup的enter和leave來實(shí)現(xiàn)。他會根據(jù)key的區(qū)別來判斷是不是新添加的癞埠,然后就會像我們通常觸發(fā)動畫一樣來toggle css的class馍忽。
組件初始化渲染的話,我們可以使用transitionAppear這個來添加動畫燕差。注意初始化渲染的時候遭笋,所有的children是appear,然后后來添加進(jìn)的就是enter了徒探。
使用ReactCSSTransitionGroup我們得不到動畫結(jié)束的通知瓦呼,也無法為了動畫加上更復(fù)雜的邏輯,想定制化测暗,就得使用ReactTransitionGroup了央串。
如果想禁掉某些動畫,我們可以設(shè)置為false碗啄。
ReactTransitionGroup
這個玩意功能強(qiáng)大的多质和,他提供了在動畫生命周期里能夠執(zhí)行的方法。使用到的時候再思考吧稚字。
Two-Way Binding Helpers
ReactLink是個方便的在react里面實(shí)現(xiàn)雙向綁定的工具饲宿。但是這個在新版本被廢棄了厦酬,還是推薦通過onchange來設(shè)置值。
雙向綁定實(shí)際上強(qiáng)制性的要求了DOM完全等于react的state瘫想,這點(diǎn)雖然其實(shí)有很廣的范圍仗阅,React提供了ReactLink來幫我們簡單的封裝了setState和onChange方法。他并沒有實(shí)際上改變react的單項(xiàng)數(shù)據(jù)流国夜。最好別用~
Test Utilities
React提供了非常棒的測試語法减噪。配合Jest這層依賴于Jsdom的,我們可以寫腳本測試整個的渲染以及事件邏輯车吹。
我們可以直接寫腳本模擬點(diǎn)擊筹裕,模擬輸入,模擬鍵盤事件窄驹。
類似于ReactTestUtils.Simulate.click(node);
我們可以renderIntoDocument然后進(jìn)行各種類型判斷以及事件觸發(fā)檢驗(yàn)朝卒。
不依賴于Jest蓄诽,不依賴于DOM,我們也可以render組件隆夯,使用如下的Shallow rendering骚秦。
Shallow rendering
使用這個組件我們可以脫離DOM來渲染組件,但是這只是一層渲染澳迫,子組件不會被渲染。我們只能夠檢查output的信息。功能其實(shí)還是很少的扯罐。refs也不支持,function也不支持烦衣。
Cloning ReactElements
cloneWithProps這個組件被廢棄了歹河,現(xiàn)在只建議使用React.cloneElement。就是在想要復(fù)制一個element花吟。并且在他的原props上進(jìn)行一些修改秸歧。
Keyed Fragments
有時我們需要將兩塊元素?fù)Q位置,按照我們一般的寫法衅澈,我們會單純的給他們換位置键菱,于是這些元素就會經(jīng)歷unmount和remount兩個步驟。這是因?yàn)槲覀儧]有給他們每個模塊一個單獨(dú)的key今布。我們?nèi)绻褂胏reateFragment就可以讓元素不執(zhí)行unmount了经备。
Immutability Helpers
(這個add-on的好處在于我們可以改變外面的殼子為一個新對象,然后對象里面的屬性會自動重用老的部默。等于就是一個淺復(fù)制侵蒙,然后我們就可以在子組件里面使用shandowCompare來比較。)
我們有時想要改變對象的里面的某個屬性傅蹂,然后其他的不想改變纷闺。例如下圖算凿。
var old = {a:1,b:{c:1,d:{e:12}},r:{f:1}};
var newData = Update(old,{b:{c:{$set:2}}});
console.log(old === newData);//false
console.log(old.b === newData.b);//false
console.log(old.b.d === newData.b.d);//true
console.log(old.r === newData.r);//true
PureRenderMixin
就是如果你的組件是pure的,就是說給不變的props和state急但,render同樣的結(jié)果澎媒。可以直接mixins這個插件波桩。其實(shí)就是shouldComponentUpdate里面返回了一個shandowCompare而已戒努。
Performance Tools
(這個是個非常好的提供性能的工具,可以讓我們查看一定的操作之后镐躲,我們頁面組件重新渲染的次數(shù)储玫,可以讓我們進(jìn)行組件的優(yōu)化,使用可以參照本項(xiàng)目DEMO里的那個debug-panel萤皂,這個是勐喆開發(fā)的一個查看工具撒穷,內(nèi)部調(diào)用了start,stop裆熙,printWasted端礼,getLastMeasurement等方法)
這里有個Perf.printWasted,這個是react內(nèi)部做的深層次比對入录,發(fā)現(xiàn)沒有變化蛤奥,于是DOM沒有觸及,這一塊的浪費(fèi)我們可以在shouldComponentUpdate里面通過return false來進(jìn)行阻止僚稿。
Shandow Compare
這個是個最淺層的比較凡桥,會對對象的每個屬性進(jìn)行嚴(yán)格等于的比較,然后都相等就返回false蚀同,有改變的話就返回true缅刽。代表著需要更新。
Advanced Performance
人們使用react的原因在于他們希望網(wǎng)站是快速的蠢络,并且是響應(yīng)的衰猛。每次state的改變導(dǎo)致重新render整個子樹讓人們想知道這樣是否影響了性能,React使用了一些聰明的技術(shù)來減少需要更新UI時的DOM操作刹孔。
首先線上環(huán)境要使用壓縮過的production build
Avoiding reconciling the DOM
React使用的是虛擬DOM腕侄。這種平行的關(guān)系阻止了React直接創(chuàng)建和接觸真實(shí)的DOM。每次React的props和state改變的話芦疏。React都會生成一個新的虛擬DOM來和老的比較冕杠,如果不相等的話,React才會盡可能小的改變虛擬DOM酸茴。
在這之上分预,React提供了一個組件的生命周期的方法,shouldComponentUpdate薪捍,這個方法來阻止虛擬DOM比較以及可能的最終的DOM的更改笼痹。讓開發(fā)者來縮短整個過程配喳。這個值默認(rèn)返回true,默認(rèn)執(zhí)行比較以及更新凳干。
我們很多時候的比較其實(shí)只是引用地址的比較(shandow compare)晴裹,這個基本上都是true的,因?yàn)槲覀兪窃谕粋€對象上修改的救赐。
我們可以使用Immutable這個東西來創(chuàng)建不同的對象涧团,或者使用Object.assign來做這件事情。
Context
React讓我們很容易的跟蹤數(shù)據(jù)流的走向经磅,因?yàn)樗际茄刂M件樹的結(jié)構(gòu)一層層props傳遞下去的泌绣。但是有時我們不想要一層層的傳遞下去,我們可以使用Context這個東西预厌。(這個是個實(shí)驗(yàn)性質(zhì)的屬性阿迈,將來可能會修改)
我們在父組件中(context的提供者)申明好childContextTypes和getChildContext。然后我們在子組件里面申明好contextTypes就可以拿到相關(guān)的數(shù)據(jù)了轧叽。如果不申明苗沧,那this.context就會是一個空對象。
還是建議不要使用這個東西炭晒,用了的話待逞,生命周期函數(shù)基本都會變化,會新加一個參數(shù)nextContext腰埂。會讓組件無法被重用飒焦。
REFERENCE
這一塊的太多了蜈膨,先不看好了....
FLUX
這個也先不管....
TIPS
這里主要就是一些細(xì)節(jié)的點(diǎn)了
Inline Styles
在React里面屿笼,我們想要使用行內(nèi)式樣的話,必須以對象的形式申明翁巍,而且必須是駝峰式驴一,行內(nèi)樣式本來就不推薦,這里也就了解一下感覺就夠了灶壶。
If-Else in JSX
JSX里面我們沒法使用if else肝断,因?yàn)镴SX只是一個來處理函數(shù)調(diào)用以及對象構(gòu)建語法糖,最多只能處理3目運(yùn)算符驰凛。如果想要使用if else也可以胸懈,只要在JSX外面使用就好了∏∠欤或者寫成一個自執(zhí)行的匿名函數(shù)調(diào)用趣钱。
Self-Closing Tag
就是說react component都可以自封閉,包括div什么的胚宦,因?yàn)樗麄儽旧硪簿褪莚eact的component首有。
Maximum Number of JSX Root Nodes
目前燕垃,render里面只允許返回一個root nodes。如果我們想要返回多個的話井联,我們只能用一個將他們包裝起立卜壕。
Shorthand for Specifying Pixel Values in style props
就是說在行內(nèi)的style屬性中,當(dāng)我們寫一些長度屬性的時候烙常,React會幫我們自動加上px這個單位轴捎,這里也介紹了一些不會加的,不過行內(nèi)的用處不大军掂,這里了解下就好了轮蜕。
Type of the Children props
我們在componentDidMount中可以通過this.props.children來訪問到組件內(nèi)部包裹的組件。如果包裹的數(shù)量大于1的話蝗锥,這個值就是一個數(shù)組跃洛,如果是1的話,這個值就是一個單個的值终议,并沒有用數(shù)組包起來汇竭,所以提供了React.Children utilities來訪問。
Value of null for Controlled Input
我們正常給input設(shè)置了value之后我們是無法修改他的值的穴张,但是我們把input的value設(shè)置為null或者undefined之后细燎,input就變的可以編輯狀態(tài)了(但是我這種賦值并沒有價值,這只是一種錯誤的狀態(tài))
componentWillReceiveProps Not Triggered After Mounting
這個方法并不會在初次mount的時候執(zhí)行皂甘,因?yàn)樗淖饔迷谟诒容^老的props和新的props玻驻,如果老的沒有的話,就不會觸發(fā)偿枕。
Props in getInitialState Is an Anti-Pattern
我們在getInitialState里面使用props來設(shè)置state需要注意一下璧瞬,因?yàn)間etInitialState這個方法只會在初始化的時候被執(zhí)行一次。
DOM Event Listeners in a Component
就是說我們最好在componentDidMount這個方法執(zhí)行之后進(jìn)行DOM上事件的綁定渐夸,因?yàn)檫@個時候渲染已經(jīng)完成了嗤锉。
Load Initial Data via AJAX
讓我們在componentDidMount里面拉取ajax數(shù)據(jù),然后在UnMount方法里面abort掉這個request墓塌。
False in JSX
false在jsx里面的渲染結(jié)果會有些不同瘟忱,比如false作為id或者value等等的值就會被解析為字符串“false”,如果在div中間使用{false}苫幢,就會得到一個空白的div访诱。
Communicate Between Components
想要父組件與子組件交流,很簡單的傳輸props就可以了韩肝,想要子組件與父組件交流触菜,只需要func.bind(this,i,props)這樣綁定一下就好了。
如果是沒有父子關(guān)系的組件之間的交流伞梯,我們可以設(shè)置自己的時間系統(tǒng)玫氢,在componentDidMount里面訂閱帚屉,然后在willUnmount里面取消訂閱。
或者按照flux來解決漾峡。
Expose Component Functions
將方法暴露給父組件來調(diào)用攻旦,其實(shí)就是父組件創(chuàng)建的時候給個ref值,然后在父組件里面使用this.refs.item1.func()就可以調(diào)用子組件的方法了生逸。
this.props.children undefined
children這個屬性并不指的是自己的render方法里面的子牢屋,而是調(diào)用這個組件里面?zhèn)魅氲淖印W⒁庹{(diào)用我們自己包裝的組件時槽袄,在里面包的div并不會渲染烙无,除非我們自己在組件里面的渲染中調(diào)用{this.props.children}來手動渲染。
Use React with Other Libraries
我們完全可以不整個的使用react遍尺,我們可以在shouldComponentUpdate里面手動return false截酷。我們可以在DidMount里面進(jìn)行一些事件的綁定。在DidUpdate進(jìn)行一些處理乾戏。但是這是件tricky的事迂苛。
Dangerously Set innerHTML
一般React會幫我們編碼一下吐到頁面上,基本不會有XSS攻擊鼓择,但是有時我們想要自己生成html吐到頁面上三幻,react提供了dangerouslySetInnerHTML這個function,傳入的數(shù)據(jù)是{__html:'haha'}呐能,注意這個就是有風(fēng)險的念搬,而且我們基本完全可以避免,除非一些非常特別的case摆出。
接下來會細(xì)讀一下react的reference和flux朗徊。
文章可以直接訪問我的前端網(wǎng)站來查看
平時的日常整理也會記錄上去。