欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React精髓!一篇全概括小結(jié)(急速)

 更新時(shí)間:2019年05月23日 10:43:36   作者:張不慫  
這篇文章主要介紹了React精髓!一篇全概括小結(jié)(急速),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

學(xué)和使用react有一年多了,最近想在梳理一下react基礎(chǔ)知識(shí),夯實(shí)基礎(chǔ),激流勇進(jìn)~
關(guān)于reacr-router,redux,redux-saga后續(xù)都會(huì)慢慢輸出,希望各位看官老爺持續(xù)關(guān)注~~要是能給個(gè)贊鼓勵(lì)一下就更贊了~

提醒一下:

看完之后抓緊時(shí)間趁熱打鐵,redux,react-redux,redux-saga

react基礎(chǔ)知識(shí)速覽

1、什么是JSX?

一個(gè)JSX語(yǔ)法的示例,如下所示

const element = <h1>Hello, world!</h1>;

這種語(yǔ)法形式,既不是HTML,也不是字符串,而是稱(chēng)之為JSX,是React里用來(lái)描述UI和樣式的語(yǔ)法,JSX最終會(huì)被編譯為合法的JS語(yǔ)句調(diào)用(編譯器在遇到{時(shí)采用JS語(yǔ)法進(jìn)行解析,遇到<就采用HTML規(guī)則進(jìn)行解析)

2、嵌入表達(dá)式

JSX中,可以使用花括號(hào){}嵌入任意的JavaScript合法表達(dá)式,如:2 + 2、user.firstName、formatName(user)都是合法的。示例如:

const user = {
 firstName: 'Zhang',
 lastName : 'Busong'
};

const elem = (
 <h1>Hello, {formatName(user)}</h1>
);
/*
這里的(),實(shí)際上是可選的,但是React推薦加入(),這樣子就會(huì)被視為一個(gè)表達(dá)式,而不會(huì)導(dǎo)致
自動(dòng)插入分號(hào)的問(wèn)題
*/

ReactDOM.render(
 element,
 document.getElementById('app')
)

3、JSX也是一種表達(dá)式

JSX本身也是一種表達(dá)式,所以它可以像其他表達(dá)式一樣,用于給一個(gè)變量賦值、作為函數(shù)實(shí)參、作為函數(shù)返回值,等等。如:

function getGreeting(user) {
 if (user) {
  return <h1>Hello, {formatName(user)}</h1>
 }
 return <h1>Hello, Guest!</h1>;
}

注意:

1、在JSX中,聲明屬性時(shí)不要使用引號(hào),如果聲明屬性的時(shí)候使用引號(hào),那么將被作為字符串解析,而不會(huì)被作為一個(gè)表達(dá)式解析,如:

<div firstName="{user.firstName}" lastName={user.lastName}></div>

解析后,可以得到:

<div firstName="{user.firstName}" lastName="Lau"></div>

因此,當(dāng)我們需要使用一個(gè)字符串字面量的時(shí)候,可以使用引號(hào),但是如果要作為表達(dá)式解析的時(shí)候,則不應(yīng)當(dāng)使用引號(hào)

2、在JSX中,有些屬性名稱(chēng)需要進(jìn)行特殊處理。如class應(yīng)該用className代替,tabindex則用tabIndex代替。這是因?yàn)镴SX本質(zhì)上更接近于JavaScript,而class是JavaScript中的保留字。同時(shí),應(yīng)該使用camelCase來(lái)命名一個(gè)屬性,而不是使用HTML的屬性命名方式

3、JSX本身已經(jīng)做了防注入處理,對(duì)于那些不是明確編寫(xiě)的HTML代碼,是不會(huì)被解析為HTML DOM的,ReactDOM會(huì)將他們一律視為字符串,在渲染完成前就轉(zhuǎn)化為字符串,所以可以防止XSS攻擊

4、如果JSX標(biāo)簽是閉合的,那么結(jié)尾需要用/>,另外,JSX標(biāo)簽是可以互相嵌套的,這和HTML里是一樣的

4、JSX實(shí)質(zhì)

JSX通過(guò)babel編譯,而babel實(shí)際上把JSX編譯給React.createElement()調(diào)用。如下JSX代碼:

const element = (
 <h1 className="greeting">
  Hello, world!
 </h1>
);

是等同于以下的語(yǔ)句的:

const elem = React.createElement(
 'h1',
 {className: 'greeting'},
 'Hello, world!'
);

React.createElement()方法會(huì)首先進(jìn)行一些避免BUG的檢查,然后返回類(lèi)似以下例子的對(duì)象:

const element = {
 type: 'h1',
 props: {
  className: 'greeting',
  children: 'Hello, world'
 }
}

這樣的對(duì)象,則稱(chēng)為React元素,代表所有呈現(xiàn)在屏幕上的東西。React正是通過(guò)讀取這些對(duì)象來(lái)構(gòu)建DOM,并且保持?jǐn)?shù)據(jù)和UI同步的

5、元素渲染

元素(elements)是構(gòu)成React應(yīng)用的最小單元,元素描述了想要在屏幕中看到的內(nèi)容,如:

const element = <h1>Hello, world</h1>;

和DOM元素不同的是,React元素是純對(duì)象,創(chuàng)建的代價(jià)低。并且React會(huì)進(jìn)行優(yōu)化處理,只把有必要的變化更新到DOM上。此外,元素和組件的概念,是不一樣的,組件是由元素組成的。

6、將元素渲染進(jìn)DOM

在React中,使用ReactDOM.render()方法來(lái)將React元素渲染進(jìn)一個(gè)DOM中。如:

ReactDOM.render(
 element,
 document.getElementById('root')
)

React元素是不可變的,所以一旦一個(gè)元素創(chuàng)建完成后,我們是無(wú)法改變其內(nèi)容或者屬性的。一個(gè)元素就像是動(dòng)畫(huà)里的一幀,它代表UI在某一時(shí)間點(diǎn)的樣子。如果非要使用元素來(lái)構(gòu)成可變化的UI界面,就需要使用setInterval了,如:

function tick() {
 const element = (
  <div>Now is {new Date().toLocaleTimeString()}</div>
 );
 ReactDOM.render(
  element,
  document.getElementById('root')
 );
}
setInterval(tick, 1000);

在實(shí)際開(kāi)發(fā)中,大多數(shù)React應(yīng)用只會(huì)調(diào)用一次ReactDOM.render(),所以更好的方式是使用有狀態(tài)組件

7、組件和Props

組件(component)能夠?qū)I劃分為獨(dú)立的、可復(fù)用的部分,這樣我們就只需專(zhuān)注于構(gòu)建每一個(gè)單獨(dú)的部件。
從概念上看,組件就像是函數(shù):接受任意的輸入(稱(chēng)為屬性,Props),返回React元素。React中有兩種定義組件的方式:函數(shù)定義和類(lèi)定義

1、函數(shù)定義組件

這種方式是最簡(jiǎn)單的定義組件的方式,就像寫(xiě)一個(gè)JS函數(shù)一樣,如:

function Welcome (props) {
 return <h1>Hello, {props.name}</h1>;;
}

2、類(lèi)定義組件

還可以使用ES6里的類(lèi)來(lái)定義一個(gè)組件,如下所示:

class Welcome extends React.Component {
 render () {
  return <h1>Hello, {this.props.name}<h1>;
 }
}

這種方式比起函數(shù)定義方式則更加靈活

3、組件渲染

先前,我們遇到的React元素只是呈現(xiàn)一個(gè)DOM標(biāo)簽,如:

const element = <div />

然而,React元素也可以是用戶(hù)自定義的組件,如:

const element = <Welcome name="Tom" />

Welcome組件中聲明了一個(gè)屬性name="Tom",而這個(gè)屬性,將以props.name的方式傳遞給組件,如下方式:

function Welcome (props) {
 return <h1>Hello, {props.name}</h1>;
}

此時(shí),對(duì)于以下的代碼:

ReactDOM.render(
 <Welcome name="張不慫" />,
 document.getElementById('root')
)

最終就會(huì)以<h1>Hello, 張不慫</h1>的方式呈現(xiàn)。在這個(gè)過(guò)程中,發(fā)生了如下的事情:

  • 對(duì)<Welcome name="張不慫" />元素調(diào)用了ReactDOM.render()豐富
  • React將{ name: '張不慫' }作為props實(shí)參來(lái)調(diào)用Welcome組件
  • Welcome完成渲染,返回<h1>Hello, 張不慫</h1>元素
  • ReactDOM計(jì)算最小更新代價(jià),然后更新DOM

4、組合組件

組件是可以組合的。即組件內(nèi)部可以引用其他組件,如:

function Welcome (props) {
 return <h1>Hello, {props.name}</h1>;
}

function App () {
 return (
  <div>
   <Welcome name="Tom" />
   <Welcome name="Jack" />
   <Welcome name="Mike" />
  </div>
 )
}

ReactDOM.render(
 <App />,
 document.getElementById('root')
)

注意: 在React中,組件必須返回單一的根元素,這也是為什么App組件中需要用<div>標(biāo)簽包裹的原因。如以下的方式,是錯(cuò)誤的(因?yàn)樗?個(gè)根元素):

function App () {
 return (
  <Welcome name="Tom" />
  <Welcome name="Jack" />
  <Welcome name="Mike" />
 )
}

5、屬性是只讀的

考慮以下這種情況:

function sum (a, b) {
 return a + b;
}

這種函數(shù)稱(chēng)為純函數(shù):它不改變自己的輸入值,且總是對(duì)相同的輸入返回相同的結(jié)果。

與之對(duì)立的,則是非純函數(shù),如:

function withdraw (account, amount) {
 account.total -= amount;
}

非純函數(shù)在函數(shù)內(nèi)改變了輸入的參數(shù)。在React中,無(wú)論是通過(guò)function還是class聲明組件,我們都不應(yīng)該修改它自身的屬性(props)。雖然React相當(dāng)靈活,但是它也有一個(gè)嚴(yán)格的規(guī)定:所有的React組件都必須像純函數(shù)那樣來(lái)使用它們的props

8、State與生命周期

使用類(lèi)定義組件有一些額外的好處,如擁有本地狀態(tài)這一特性。

以下是一個(gè)類(lèi)定義組件

class Clock extends React.Component {
 render () {
  return (
   <div>
    <h1>Hello, world!</h1>
    <h2>Now is {this.props.date.toLocaleTimeString()}</h2>
   </div>
  );
 }
}

需要注意的有:

類(lèi)名即為組件名(無(wú)論是函數(shù)定義組件還是類(lèi)定義組件,組件名稱(chēng)的首字母都必須大寫(xiě),并且繼承自React.Component)
使用 render() 方法,用來(lái)返回需要呈現(xiàn)的內(nèi)容

1、在類(lèi)中加入state

state是屬于一個(gè)組件自身的。我們可以在類(lèi)的構(gòu)造函數(shù)constructor中來(lái)初始化狀態(tài),如:

constructor (props) {
 super(props)
 this.state = {
  date: new Date()
 }
}

如此一來(lái),我們就可以在render()函數(shù)中使用this.state.xxx來(lái)引用一個(gè)狀態(tài)

2、生命周期

在應(yīng)用里,往往都會(huì)有許許多多的組件。在組件銷(xiāo)毀后,回收和釋放它們所占據(jù)的資源非常重要。

在時(shí)鐘應(yīng)用的例子里,我們需要在第一次渲染到DOM的時(shí)候設(shè)置一個(gè)定時(shí)器,并且需要在相應(yīng)的DOM銷(xiāo)毀后,清除這個(gè)定時(shí)器。那么,這種情況下,React為我們提供了生命周期的鉤子函數(shù),方便我們進(jìn)行使用。在React中,生命周期分為:

1)Mount 已插入真實(shí)DOM
2)Update 正在重新渲染
3)Unmount 已移出真實(shí)DOM

而相應(yīng)的,生命周期鉤子函數(shù)有:

  • componentWillMount
  • componentDidMount
  • componentWillUpdate(newProps, nextState)
  • componentDidUpdate(prevProps, prevState)
  • componentWillUnmount()

此外,還有兩種特殊狀態(tài)的處理函數(shù):

  • componentWillReceiveProps(nextProps) 已加載的組件收到新的參數(shù)時(shí)調(diào)動(dòng)
  • shouldComponentUpdate(nextProps, nextState) 組件判斷是否重新渲染時(shí)調(diào)用

因此,基于生命周期鉤子函數(shù),我們可以實(shí)現(xiàn)一個(gè)時(shí)鐘應(yīng)用如下:

class Clock extends React.Component {
 constructor (props) {
  super(props);
  this.state = {
   date: new Date()
  }
 }
 tick () {
  this.setState({
   date: new Date()
  });
 }
 componentDidMount () {
  this.timerId = setInterval(() => {
   this.tick()
  }, 1000);
 }
 componentWillUnmount () {
  clearInterval(this.timerId);
 }
 render () {
  return (
   <div>Now is {this.state.date.toLocaleTimeString()}</div>
  );
 }
}

需要注意的是:

1)render()里用不到的state,不應(yīng)該聲明在state里
2)不能直接使用this.state.xxx = xxx的方式來(lái)改變一個(gè)state的值,應(yīng)該使用this.setState()。如:

setName () {
 this.setState({
  name: '張不慫'
 })
}

this.setState()會(huì)自動(dòng)覆蓋this.state里相應(yīng)的屬性,并觸發(fā)render()重新渲染。

3)狀態(tài)更新可能是異步的

React可以將多個(gè)setState()調(diào)用合并成一個(gè)調(diào)用來(lái)提升性能。且由于this.props和this.state可能是異步更新的,所以不應(yīng)該依靠它們的值來(lái)計(jì)算下一個(gè)狀態(tài)。這種情況下,可以給setState傳入一個(gè)函數(shù),如:

this.setState((prevState, props) => ({
 counter: prevState.counter + props.increment
}));

9、事件處理

React元素的事件與DOM元素類(lèi)似,不過(guò)也有一些區(qū)別,如:

1)React事件使用camelCase命名(onClick),而不是全小寫(xiě)的形式(onclick)
2)使用JSX,傳入的是事件的句柄,而不是一個(gè)字符串

如以下的HTML:

<button onclick="increment()">ADD</button>

使用React的方式描述如:

<button onClick={increment}>ADD</button>

還有一個(gè)不同在于,在原生DOM中,我們可以通過(guò)返回false來(lái)阻止默認(rèn)行為,但是這在React中是行不通的,在React中需要明確使用preventDefault()來(lái)阻止默認(rèn)行為。如:

function ActionLink () {
 function handleClick (e) {
  e.preventDefault();
  alert('Hello, world!');
 }

 return (
  <a href="#" rel="external nofollow" onClick={handleClick}>Click Me</a>
 );
}

這里,事件回調(diào)函數(shù)里的event是經(jīng)過(guò)React特殊處理過(guò)的(遵循W3C標(biāo)準(zhǔn)),所以我們可以放心地使用它,而不用擔(dān)心跨瀏覽器的兼容性問(wèn)題。

注意: 在使用事件回調(diào)函數(shù)的時(shí)候,我們需要特別注意this的指向問(wèn)題,因?yàn)樵赗eact里,除了構(gòu)造函數(shù)和生命周期鉤子函數(shù)里會(huì)自動(dòng)綁定this為當(dāng)前組件外,其他的都不會(huì)自動(dòng)綁定this的指向?yàn)楫?dāng)前組件,因此需要我們自己注意好this的綁定問(wèn)題,
通常而言,在一個(gè)類(lèi)方式聲明的組件里使用事件回調(diào),我們需要在組件的constructor里綁定回調(diào)方法的this指向,如:

class Counter extends React.Component {
 constructor (props) {
  super(props);
  this.state = {
   counter: 0
  }
  // 在這里綁定指向
  this.increment = this.increment.bind(this);
 }
 increment () {
  this.setState({
   counter: this.state.counter + 1
  });
 }
 render () {
  return (
   <div>
    The counter now is: {this.state.counter}
    <button onClick={this.increment}>+1</button>
   </div>
  );
 }
}

當(dāng)然,我們還有另外一種方法來(lái)使用箭頭函數(shù)綁定指向,就是使用實(shí)驗(yàn)性的屬性初始化語(yǔ)法,如:

class Counter extends React.Component {
 increment: () => {
  this.setState({
   counter: this.state.counter + 1
  });
 }
 // ...
}

3)像事件處理程序傳遞參數(shù)

我們可以為事件處理程序傳遞額外的參數(shù),方式有以下兩種:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

需要注意的是,使用箭頭函數(shù)的情況下,參數(shù)e要顯式傳遞,而使用bind的情況下,則無(wú)需顯式傳遞(參數(shù)e會(huì)作為最后一個(gè)參數(shù)傳遞給事件處理程序)

10、條件渲染

在React里,我們可以創(chuàng)建不同的組件來(lái)封裝我們需要的功能。我們也可以根據(jù)組件的狀態(tài),只渲染組件中的一部分內(nèi)容,而條件渲染就是為此而準(zhǔn)備的。在React中,我們可以像在JavaScript中寫(xiě)條件語(yǔ)句一樣地寫(xiě)條件渲染語(yǔ)句,如:

function Greet(props) {
 const isLogined = props.isLogined;
 if (isLogined) {
  return <div>Hello !</div>;
 }
 return <div>Please sign in</div>;
}

ReactDOM.render(
 <Greet isLogined={true} />,
 document.getElementById('root')
);

這將渲染出:

<div>Hello !</div>

1、使用變量來(lái)存儲(chǔ)元素

我們也可以使用變量來(lái)存儲(chǔ)元素,如:

function LogBtn(props) {
 var button;
 const isLogined = props.isLogined;
 if (isLogined) {
  button = <button>退出</button>
 } else {
  button = <button>登陸</button>
 }
 return <div>You can {button}</div>;
}

ReactDOM.render(
 <LogBtn isLogined={false} />,
 document.getElementById('root')
);

2、使用&&運(yùn)算符進(jìn)行渲染

由于JavaScript語(yǔ)法對(duì)待&&運(yùn)算符的性質(zhì),我們也可以使用&&運(yùn)算符來(lái)完成條件渲染,如:

function LogBtn(props) {
 var button;
 const isLogined = props.isLogined;
 return (
  <div>Hello
  {!isLogined && (
   <button>請(qǐng)登陸</button>
  )}
  </div>
 )
}

當(dāng)props.isLogined為false的時(shí)候,就會(huì)渲染出:

<div>Hello <button>請(qǐng)登錄</button></div>

3、使用三目運(yùn)算符進(jìn)行渲染

我們可能已經(jīng)發(fā)現(xiàn)了,其實(shí)JSX可以像一個(gè)表達(dá)式那樣子靈活使用,所以,我們自然也可以使用三目運(yùn)算符進(jìn)行渲染,如:

function LogBtn (props) {
 const isLogined = props.isLogined;
 return (
  <div>You can 
   <button>{isLogined ? '退出' : '登陸'}</button>
  </div>
 )
}

4、阻止整個(gè)組件的渲染

有時(shí)候,我們希望是整個(gè)組件都不渲染,而不僅僅是局部不渲染,那么這種情況下,我們就可以在render()函數(shù)里返回一個(gè)null,來(lái)實(shí)現(xiàn)我們想要的效果,如:

function LogBtn (props) {
 const isLogined = props.isLogined;
 const isShow = props.isShow;
 if (isShow) {
  return (
   <div>You can 
    <button>{isLogined ? '退出' : '登陸'}</button>
   </div>
  )
 }
 return null;
}

注意: 組件里返回null不會(huì)影響組件生命周期的觸發(fā),如componentWillUpdate和componentDidUpdate仍然會(huì)被調(diào)用

11、列表渲染與keys

在JavaScript中,我們可以使用map()函數(shù)來(lái)對(duì)一個(gè)數(shù)組列表進(jìn)行操作,如:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(number => number*2);
console.log(doubled); // 得到[2, 4, 6, 8, 10]

同樣的,在React里,我們也可以使用map()來(lái)進(jìn)行列表渲染,如:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map(number => {
 return (
  <li>{number}</li>
 )
});

ReactDOM.render(
 <ul>{listItems}</ul>,
 document.getElementById('root')
)

這將得到:

<ul><li>1</li>
 <li>2</li>
 <li>3</li>
 <li>4</li>
 <li>5</li>
</ul>

當(dāng)然,我們還可以進(jìn)行更好的封裝,如:

function NumberList (props) {
 const numbers = props.numbers;
 const listItems = numbers.map(number => {
  return (
   <li>{number}</li>
  )
 });

 return <ul>{listItems}</ul>
}

當(dāng)我們運(yùn)行以上的代碼的時(shí)候,會(huì)發(fā)現(xiàn)控制臺(tái)提示:Each child in an array or iterator should have a unique "key" prop,因此,我們需要為列表項(xiàng)的每一個(gè)項(xiàng)分配一個(gè)key,來(lái)解決這個(gè)問(wèn)題,通常而言,我們可以使用以下幾種方式來(lái)提供key:

使用數(shù)據(jù)項(xiàng)自身的ID,如<li key={item.itemId}>
使用索引下標(biāo)(index),如:

const listItems = numbers.map((number, index) => {
 <li key={index}>{number}</li>
});

但是React不推薦在需要重新排序的列表里使用索引下標(biāo),因?yàn)闀?huì)導(dǎo)致變得很慢。
注意: 只有在一個(gè)項(xiàng)的同胞里區(qū)分彼此的時(shí)候,才需要使用到key,key不需要全局唯一,只需要在一個(gè)數(shù)組內(nèi)部區(qū)分彼此時(shí)唯一便可。key的作用是給React一個(gè)提示,而不會(huì)傳遞給組件。如果我們?cè)诮M件內(nèi)需要同樣的一個(gè)值,可以換個(gè)名字傳遞,如:

const content = posts.map(post => (
 <Post key={post.id} id={post.id} title={post.title} />
));

12、表單

表單和其他的React中的DOM元素有所不同,因?yàn)楸韱卧厣鷣?lái)就是為了保存一些內(nèi)部狀態(tài)。在React中,表單和HTML中的表單略有不同

1、受控組件

HTML中,<input>、<textarea>、<select>這類(lèi)表單元素會(huì)維持自身狀態(tài),并根據(jù)用戶(hù)輸入進(jìn)行更新。不過(guò)React中,可變的狀態(tài)通常保存在組件的this.state中,且只能用setState()方法進(jìn)行更新,如:

class NameForm extends React.Component {
 constructor (props) {
  super(props);
  this.state = {
   value: ''
  }
  this.handleChange = this.handleChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
 }
 handleChange (event) {
  this.setState({
   value: event.target.value
  });
 }
 handleSubmit (event) {
  alert('Your name is '+this.state.value);
  event.preventDefault();
 } 
 render () {
  return (
   <form onSubmit={this.handleSubmit}>
   Name: <input type="text" value={this.state.value} onChange={this.handleChange} />
   <input type="submit" value="Submit" />
   </form>
  )
 }
}

和HTML中不同的是,React中的textarea并不需要寫(xiě)成<textarea></textarea>的形式,而是寫(xiě)成<textarea value="" ... />的形式便可。而對(duì)于HTML中的select標(biāo)簽,通常做法是:

<select>
 <option value="A">A</option>
 <option value="B" selected>B</option>
 <option value="C">C</option>
</select>

但是React中,不需要在需要選中的option處加入selected,而只需要傳入一個(gè)value,就會(huì)自動(dòng)根據(jù)value來(lái)選中相應(yīng)的選項(xiàng),如:

<select value="C">
 <option value="A">A</option>
 <option value="B">B</option>
 <option value="C">C</option>
</select>

那么如上述例子,C所在的這個(gè)option就會(huì)被選中

2、多個(gè)輸入的解決辦法

通常一個(gè)表單都有多個(gè)輸入,如果我們?yōu)槊恳粋€(gè)輸入添加處理事件,那么將會(huì)非常繁瑣。好的一個(gè)解決辦法是,使用name,然后根據(jù)event.target.name來(lái)選擇做什么。如:

class Form extends React.Component {
 constructor (props) {
  super(props);
  this.state = {
   name: '',
   gender: '男',
   attend: false,
   profile: ''
  };
  this.handleInputChange = this.handleInputChange.bind(this);
  this.handleSubmit = this.handleSubmit.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
  });
 }
 handleSubmit (event) {
  this.setState({
   profile: `姓名:${this.state.name},${this.state.gender},${this.state.attend ? '參加' : '不參加'}活動(dòng)`
  });
  event.preventDefault();
 } 
 render () {
  return (
   <form>
   <p>姓名:<input name="name" value={this.state.name} onChange={this.handleInputChange} /></p>
   <p>性別:
    <select name="gender" value={this.state.gender} onChange={this.handleInputChange}>
     <option value="男">男</option>
     <option value="女">女</option>
    </select>
   </p>
   <p>是否參加:<input name="attend" type="checkbox" onChange={this.handleInputChange} checked={this.state.attend} /></p>
   <input type="submit" value="Submit" onClick={this.handleSubmit} />
   <p>您的報(bào)名信息:{this.state.profile}</p>
   </form>
  )
 }
}

3、非受控組件

大多數(shù)情況下,使用受控組件實(shí)現(xiàn)表單是首選,在受控組件中,表單數(shù)據(jù)是交由React組件處理的。如果想要讓表單數(shù)據(jù)由DOM處理(即數(shù)據(jù)不保存在React的狀態(tài)里,而是保存在DOM中),那么可以使用非受控組件,使用非受控組件,可以無(wú)需為每個(gè)狀態(tài)更新編寫(xiě)事件處理程序,使用ref即可實(shí)現(xiàn),如:

class NameForm extends React.Component {
 constrcutor(props) {
  super(props)
 }
 handleSubmit(event) {
  console.log('A name was submitted: ', this.input.value)
  event.preventDefault()
 }
 render() {
  return (
   <form onSubmit={this.handleSubmit}>
    <label>
    Name: <input type="text" ref={input => this.input = input} />
    </label>
    <input type="submit" value="submit" />
   </form>
  )
 }
}

對(duì)于非受控組件,如果要指定默認(rèn)值,那么可以使用defaultValue,如:

<input type="text" defaultValue="Hello" ref={input => this.input = input} />

相應(yīng)的,type="checkbox"和type="radio",則使用defaultChecked

13、狀態(tài)提升

當(dāng)需要幾個(gè)組件共用狀態(tài)數(shù)據(jù)的時(shí)候,可以使用狀態(tài)提升技術(shù)。核心思想在于:把數(shù)據(jù)抽離到最近的共同父組件,父組件管理狀態(tài)(state),然后通過(guò)屬性(props)傳遞給子組件。如實(shí)現(xiàn)一個(gè)貨幣轉(zhuǎn)換的組件,可以如下:

1、首先定義轉(zhuǎn)換函數(shù)

function USD2RMB (amount) {
 return amount * 6.7925;
}

function RMB2USD (amount) {
 return amount * 0.1472;
}

function convert (amount, typeFn) {
 return typeFn(amount);
}

2、定義組件

我們希望在RMB的輸入表單上上輸入的時(shí)候,USD的輸入表單上的數(shù)值也同步更新,這種情況下,如果RMB組件自己管理自己的狀態(tài),是很難以實(shí)現(xiàn)的,因此,我們需要讓這個(gè)狀態(tài)提升自父組件進(jìn)行管理。如下:

class CurrencyInput extends React.Component {
 constructor (props) {
  super(props)
  this.handleChange = this.handleChange.bind(this)
 }
 handleChange (event) {
  this.props.onInputChange(event.target.value)
 }
 render () {
  const value = this.props.value
  const type = this.props.type
  return (
   <p>{type}: <input type="text" value={value} onChange={this.handleChange} /></p>
  );
 }
}

最后定義一個(gè)共同的父組件,如下:

class CurrencyConvert extends Component {
 constructor (props) {
  super(props);
  this.state = {
   type: 'RMB',
   amount: 0
  }
  this.handleRMBChange = this.handleRMBChange.bind(this);
  this.handleUSDChange = this.handleUSDChange.bind(this);
 }
 handleRMBChange (amount) {
  this.setState({
   type: 'RMB',
   amount
  });
 }
 handleUSDChange (amount) {
  this.setState({
   type: 'USD',
   amount
  });
 }
 render () {
  const type = this.state.type;
  const amount = this.state.amount;
  const RMB = type==='RMB' ? amount : convert(amount, USB2RMB);
  const USD = type==='USD' ? amount : convert(amount, RMB2USB);
  return (
   <div>
    <p>Please Input:</p>
    <CurrencyInput type="RMB" value={RMB} onInputChange={this.handleRMBChange} />
    <CurrencyInput type="USD" value={USD} onInputChange={this.handleUSDChange} />
   </div>
  );
 }
}

14、組合vs繼承

React推崇更多的是使用組合,而非使用繼承。對(duì)于一些使用場(chǎng)景,React給出的建議如下:

1、包含關(guān)系

當(dāng)父組件不知道子組件可能的內(nèi)容是什么的時(shí)候,可以使用props.children,如:

function Article (props) {
 return (
  <section>
   <aside>側(cè)邊欄</aside>
   <article>{props.children}</article>
  </section>
 );
}

function App () {
 return (
  <Article>這是一篇文章</Article>
 );
}

這將渲染得到:

<section>
 <aside>側(cè)邊欄</aside>
 <article>這是一篇文章</article>
</section>

我們還可以自定義名稱(chēng),因?yàn)镴SX實(shí)際上會(huì)被轉(zhuǎn)化為合法的JS表達(dá)式,所以,還可以有:

function Article (props) {
 return (
  <section>
   <aside>{props.aside}</aside>
   <article>{props.children}</article>
  </section>
 );
}

function App () {
 return (
  <Article aside={
   <h1>這是一個(gè)側(cè)欄</h1>
  }>這是一篇文章</Article>
 );
}

這將渲染得到:

<section>
 <aside><h1>這是一個(gè)側(cè)欄</h1></aside>
 <article>這是一篇文章</article>
</section>

2、何時(shí)使用繼承?

在Facebook的網(wǎng)站上,使用了數(shù)以千計(jì)的組件,但是實(shí)踐證明還沒(méi)有發(fā)現(xiàn)需要使用繼承才能解決的情況。

屬性和組合為我們提供了清晰的、安全的方式來(lái)自定義組件的樣式和行為,組件可以接受任意元素,包括:基本數(shù)據(jù)類(lèi)型、React元素、函數(shù)。

如果要在組件之間復(fù)用UI無(wú)關(guān)的功能,那么應(yīng)該將其提取到單獨(dú)的JavaScript模塊中,這樣子可以在不對(duì)組件進(jìn)行擴(kuò)展的前提下導(dǎo)入并使用函數(shù)、對(duì)象、類(lèi)

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談React 屬性和狀態(tài)的一些總結(jié)

    淺談React 屬性和狀態(tài)的一些總結(jié)

    下面小編就為大家?guī)?lái)一篇淺談React 屬性和狀態(tài)的一些總結(jié)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-11-11
  • 詳解react setState

    詳解react setState

    這篇文章主要介紹了react setState的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用react,感興趣的朋友可以了解下
    2021-04-04
  • 基于antd的autocomplete的二次封裝查詢(xún)示例

    基于antd的autocomplete的二次封裝查詢(xún)示例

    這篇文章主要為大家介紹了基于antd的autocomplete的二次封裝查詢(xún)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • 完美解決react-codemirror2?編輯器需點(diǎn)擊一下或者延時(shí)才顯示數(shù)據(jù)的問(wèn)題

    完美解決react-codemirror2?編輯器需點(diǎn)擊一下或者延時(shí)才顯示數(shù)據(jù)的問(wèn)題

    這篇文章主要介紹了react-codemirror2編輯器需點(diǎn)擊一下或者延時(shí)才顯示數(shù)據(jù)的問(wèn)題,解決方法也很簡(jiǎn)單,需要手動(dòng)引入自動(dòng)刷新的插件,配置一下參數(shù)就可以了,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • react.js 翻頁(yè)插件實(shí)例代碼

    react.js 翻頁(yè)插件實(shí)例代碼

    這篇文章主要介紹了react.js 翻頁(yè)插件實(shí)例代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-01-01
  • react使用節(jié)流函數(shù)防止重復(fù)點(diǎn)擊問(wèn)題

    react使用節(jié)流函數(shù)防止重復(fù)點(diǎn)擊問(wèn)題

    這篇文章主要介紹了react使用節(jié)流函數(shù)防止重復(fù)點(diǎn)擊問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • React?Context用法小結(jié)(附完整代碼)

    React?Context用法小結(jié)(附完整代碼)

    這篇文章主要介紹了React?Context用法小結(jié)(附完整代碼),Context提供了一種新的組件之間共享數(shù)據(jù)的方式,允許數(shù)據(jù)隔代傳遞,而不必顯式的通過(guò)組件樹(shù)逐層傳遞props,本文通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • 淺談React 的引入

    淺談React 的引入

    React相比于Vue,更注重對(duì)JS的掌握,Vue把能做的都做了,只剩下最簡(jiǎn)單的讓開(kāi)發(fā)者使用,開(kāi)發(fā)者需要記憶Vue的特定指令后就可很輕松地開(kāi)發(fā)。相反,React是提供了一種思路和方式,沒(méi)有過(guò)多的限制,但要求會(huì)相對(duì)高些,需要開(kāi)發(fā)者對(duì)JS達(dá)到精通的地步才能真正運(yùn)用好React。
    2021-05-05
  • ahooks?useInfiniteScroll源碼解析

    ahooks?useInfiniteScroll源碼解析

    這篇文章主要為大家介紹了ahooks?useInfiniteScroll源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • pubsub-js在react中的使用教程

    pubsub-js在react中的使用教程

    pubsub-js?是一個(gè)用于實(shí)現(xiàn)發(fā)布-訂閱模式的 JavaScript 庫(kù),可以用于不同組件之間的通信,在 React 中,可以使用?pubsub-js?來(lái)實(shí)現(xiàn)組件之間的通信,本篇文章給大家講解pubsub-js在react中的使用,感興趣的朋友一起看看吧
    2023-10-10

最新評(píng)論