react官網(wǎng)教程基礎(chǔ)解析
1刁卜、使用redux和沒有redux锈锤,react寫法有什么不同嗎摔寨?
答:組件寫法一樣,但是state不一定交給組件內(nèi)部管理竭望,可能放到store上統(tǒng)一管理邪码。
2、認(rèn)識react市框,一個(gè)hello world霞扬!
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
3、如何使用react枫振?
答:推薦你使用ES6語法來寫react喻圃,首先你需要Babel編譯你的ES6代碼,其次粪滤,你才可以使用比如 => (箭頭函數(shù))斧拍,class(類),模板文字杖小,let和const語句等ES6語法肆汹。
4、JSX介紹
答:JSX是一種表達(dá)式予权,它有一個(gè)根標(biāo)簽昂勉,在內(nèi)部可以嵌入表達(dá)式,使用{}(大括號)包裹起來扫腺。它看起來就是html的一部分岗照,或者叫一個(gè)html模塊。
class T extends React.Component {
render() {
return <div className="left-enter" style={}>{value}</div>
}
}
從上面的代碼例子你可以看到幾個(gè)和html不同的地方笆环,class =》className攒至,style是一個(gè)object,你還可以在dom元素中使用{}插入數(shù)據(jù)躁劣。
使用JSX還可以防止XSS(跨站腳本攻擊)迫吐,因?yàn)镴SX只是表達(dá)式,它需要先轉(zhuǎn)換成字符串账忘,然后才能渲染到真實(shí)DOM上面志膀,但對于真正的黑客來說熙宇,這種做法也不是安全的。
4梧却、元素和組件的概念
react組件:
class T extends React.Component {
render() {
return <div className="left-enter" style={}>{value}</div>
}
}
react元素:
<div className="left-enter" style={}>{value}</div>
5奇颠、組件的使用
函數(shù)組件:函數(shù)組件沒有狀態(tài)和生命周期,但是你可以返回一個(gè)react元素放航。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
class組件:非常強(qiáng)大烈拒,有自己的state和生命周期。和函數(shù)組件一樣广鳍,class組件也需要返回一個(gè)react元素荆几。
class Welcome extends React.Component {
componentWillMount() {}
componentDidMount() {}
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
在一個(gè)龐大復(fù)雜的網(wǎng)站應(yīng)用中,要如何拆分組件呢赊时?官網(wǎng)上說組件拆分的越細(xì)吨铸,復(fù)用性就越強(qiáng),從實(shí)際開發(fā)中來看祖秒,這個(gè)說法沒有錯(cuò)诞吱,但是
會(huì)帶來一個(gè)比較嚴(yán)重的問題,就是組件太多竭缝,管理起來不方便房维。有人使用第三方react組件的時(shí)候,只有那些文檔非常強(qiáng)大的開源組件
才能給你的開發(fā)提高效率抬纸。如果你自己的組件也想拆分到細(xì)致咙俩,那么寫好文檔是最重要的一步。
react還提到了一點(diǎn)湿故,傳遞給組件的數(shù)據(jù)是"只讀"的阿趁,要保證組件中的數(shù)據(jù)是"純數(shù)據(jù)",輸入即輸出坛猪。那么脖阵,如果你需要在組件中修改props.data
該怎么做呢?
render() {
const { data } = this.props
//定義一個(gè)新的變量來保存修改后的值墅茉。
let _data = data + 1;
}
6独撇、組件的狀態(tài)和生命周期
前面我們提到組件分為函數(shù)組件和類組件,函數(shù)組件是無狀態(tài)躁锁,類組件有狀態(tài)和生命周期。
什么是狀態(tài)卵史?
答:通俗理解战转,就是組件不同時(shí)候的不同表現(xiàn),比如以躯,一個(gè)按鈕組件槐秧,可能有激活狀態(tài)啄踊,不可點(diǎn)擊狀態(tài),顯示狀態(tài)刁标,隱藏狀態(tài)等颠通,在react用state來保存這些狀態(tài)。
而state本身不僅僅表示組件狀態(tài)膀懈,還可以保存組件的數(shù)據(jù)顿锰。
class Button extends React.Component {
constructor(props) {
super(props);
this.state = {
isShow: true,
text: props.text,
disabled: true
};
}
render() {
const { isShow, text, disabled} = this.state
return <button disabled={disabled} style={{display: isShow ? "block" : "none"}}>{text}</button>
}
}
如果要修改state,請使用启搂,注意硼控,你不能在render函數(shù)里面直接修改state,而是要通過事件去觸發(fā)state更新胳赌。
this.setState({
isShow: false,
disabled: false
})
由于setState有批處理功能牢撼,所以該方法可能不一定同步更新,如果你需要依賴上一次的狀態(tài)和本次狀態(tài)的計(jì)算疑苫,那么需要寫成下面這種形式熏版。
this.setState((prevState, props) => {
text: prevState.text++
});
demo網(wǎng)址:http://codepen.io/hyy1115/pen/GmdOKJ?editors=0011
有時(shí)候,子組件不需要關(guān)注自身的狀態(tài)捍掺,而是通過父組件的狀態(tài)來改變撼短,這時(shí)候的子組件可以寫成函數(shù)形式,通過props傳遞父組件給的狀態(tài)乡小。
react生命周期
生命周期表示組件的一生阔加,從出生到輝煌到死亡,中間最主要也是最常用的3個(gè)狀態(tài)是:
componentWillMount:出生了满钟,把組件的狀態(tài)和屬性都設(shè)置好胜榔。
componentDidMount:渲染出來了,我不再是JSX湃番,而是真實(shí)DOM了夭织。
componentWillUnmount:要死了,死之前把遺產(chǎn)處理好吠撮。
class Button extends React.Component {
constructor(props) {
super(props);
this.state = {
isShow: true,
text: props.text,
disabled: true
};
}
componentWillMount() {
//出生了尊惰,可以給我數(shù)據(jù)和設(shè)置我的狀態(tài)
}
componentDidMount() {
//活著多好
}
componentWillUnmount() {
//要死了,把我的一生痕跡都清除
}
render() {
const { isShow, text, disabled} = this.state
return <button disabled={disabled} style={{display: isShow ? "block" : "none"}}>{text}</button>
}
}
還有其他幾個(gè)生命周期泥兰,并不是非常常用弄屡,需要用到的時(shí)候去看下別人的博客。
7鞋诗、事件處理
<button onClick={(e) => this.handleClick(e)}>
按鈕
</button>
<input type="text" onChange={(e) => this.handleClick(e)} />
8膀捷、條件渲染
前面button的例子我們已經(jīng)使用到了條件渲染,條件渲染通過state來判斷削彬,常用的是控制style全庸、className秀仲、DOM屬性,JSX壶笼。
舉幾個(gè)常用的例子神僵。
render() {
return (
<div>
{
this.state.isShow && <button>按鈕</button>
}
</div>
)
}
render() {
return (
<div>
{
this.state.isShow ? <button>按鈕</button> : <span>文本</span>
}
</div>
)
}
render() {
return <button disabled={this.state.disabled}>按鈕</button>
}
9、列表渲染
2個(gè)注意點(diǎn):
數(shù)組要判斷是否為空覆劈;
必須給一個(gè)key保礼。
render() {
const { arr } = this.state
return arr.length > 0 && arr.map((value, key) => <li key={key}>{value}</li> )
}
10、表單
我曾經(jīng)經(jīng)歷過的一次阿里的面試墩崩,就考到了react表單的知識點(diǎn)氓英。
受控組件:由react控制輸入的表單組件。
在下面的例子中鹦筹,input的value值由state來決定铝阐,用戶輸入觸發(fā)onChange事件,然后更新state铐拐,達(dá)到修改value的目的徘键。
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
return (
<input type="text" value={this.state.value} onChange={this.handleChange} />
);
}
}
或許你沒看出來和正宗input元素的區(qū)別,看一個(gè)真實(shí)DOM元素的例子,value由inupt自身維護(hù)遍蟋,我們沒有給value綁定值吹害。
<input type="text">
textarea和input是一樣的用法。
select有些許不同虚青,將value綁定到select上它呀,而不是option。
<select value={this.state.value} onChange={this.handleChange}>
<option value="1">1</option>
<option value="2">2</option>
</select>
還有一種是多個(gè)輸入框的情況棒厘,比如登錄纵穿,有賬號、密碼等奢人,這時(shí)候操作這些不同的input可以通過ref或者name谓媒,class,id等方法去setState何乎,看
官方demo句惯。
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</form>
);
}
}
不受控組件:很簡單,就是DOM自己維護(hù)狀態(tài)的組件支救,不受react控制抢野。你可以給它設(shè)置defaultValue,但是不能去setState各墨。
<input type="text" ref={(input) => this.input = input} defaultValue="默認(rèn)值"/>
相信有人會(huì)試過設(shè)置defaultValue之后執(zhí)行了setState去修改value指孤,這樣做控制臺(tái)會(huì)發(fā)出警告。
總結(jié):受控組件是指受react控制的組件欲主,表單組件中的value和state同步邓厕,不受控組件是指不受react控制的組件,表單組件中的
value不通過state同步扁瓢,只能操作DOM去讀取value详恼。
11、狀態(tài)提升
你一定聽說過變量提升引几,函數(shù)提升昧互,那么狀態(tài)提升是什么呢?
首先你得了解雙向綁定和單向數(shù)據(jù)流伟桅,雙向綁定中敞掘,數(shù)據(jù)可以在不同的組件之間實(shí)現(xiàn)共享,這樣做的確有很大的好處楣铁,但是在react中玖雁,
不推薦使用雙向綁定,而是使用狀態(tài)提升的方式盖腕。
記得和阿里的一個(gè)面試官聊的時(shí)候赫冬,他要求我用react實(shí)現(xiàn)雙向綁定,而我認(rèn)為react應(yīng)該采用狀態(tài)提升來實(shí)現(xiàn)溃列。最后沒說服他劲厌,或許讓Dan來
和他聊聊才有用,哈哈听隐。
狀態(tài)提升:state推崇單向數(shù)據(jù)流补鼻,數(shù)據(jù)從父組件通過props流向子組件,如果你在子組件中雅任,需要修改state來和其他子組件共享數(shù)據(jù)更新风范,
你需要使用回調(diào)函數(shù)給使數(shù)據(jù)更新給父組件,然后從父組件流向其他的子組件椿访,這樣做是保證數(shù)據(jù)有單一的來源乌企。
如果實(shí)子組件和子組件之間任意共享數(shù)據(jù),那么成玫,后期維護(hù)會(huì)比較痛苦加酵,特別是找bug的時(shí)候。
看一個(gè)狀態(tài)提升的例子吧哭当。
class Child extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.props.upDateValue(e.target.value);
}
render() {
const {name, value} = this.props;
return (
<div>
<p>{name}:</p>
<input value={value}
onChange={this.handleChange}
/>
</div>
);
}
}
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {value: '', name: ''};
this.upDateValue = this.upDateValue.bind(this);
}
upDateValue(value) {
this.setState({value: value})
}
render() {
const {value} = this.state;
return (
<div>
<Child name="組件1" value={value} upDateValue={this.upDateValue} />
<Child name="組件2" value={value} upDateValue={this.upDateValue} />
</div>
);
}
}
ReactDOM.render(
<Demo />,
document.getElementById('root')
);
demo網(wǎng)址:http://codepen.io/hyy1115/pen/xdjoZQ?editors=0011
12猪腕、選擇組合還是繼承?
用過原生js或者jQuery的同學(xué)可能對基礎(chǔ)非常熟悉钦勘,繼承可以實(shí)現(xiàn)擴(kuò)展很多功能陋葡。
在react組件開發(fā)中,我們的每個(gè)react組件都是繼承于React.Component彻采。
class MyComponent extends React.Component {
}
我們不推薦你繼承MyComponent腐缤。
//不推薦
class NextComponent extends MyComponent {
}
你應(yīng)該充分利用react組件的強(qiáng)大性能捌归,開發(fā)各種你需要的組件繼承至React.Component。組件之間的嵌套非常強(qiáng)大岭粤,你可以嵌套函數(shù)組件惜索,嵌套類組件。
詳情前往:https://facebook.github.io/react/docs/composition-vs-inheritance.html