學和使用react有一年多了,最近想在梳理一下react基礎知識,夯實基礎,激流勇進~ 關於reacr-router,redux,redux-saga後續都會慢慢輸出,希望各位看官老爺持續關注~~~
react基礎知識速覽
1、什麼是JSX?
一個JSX語法的示例,如下所示
const element = <h1>Hello, world!</h1>;
複製程式碼
這種語法形式,既不是HTML,也不是字串,而是稱之為JSX,是React裡用來描述UI和樣式的語法,JSX最終會被編譯為合法的JS語句呼叫(編譯器在遇到{
時採用JS語法進行解析,遇到<
就採用HTML規則進行解析)
2、嵌入表示式
JSX中,可以使用花括號{}
嵌入任意的JavaScript合法表示式,如:2 + 2
、user.firstName
、formatName(user)
都是合法的。示例如:
const user = {
firstName: 'Zhang',
lastName : 'Busong'
};
const elem = (
<h1>Hello, {formatName(user)}</h1>
);
/*
這裡的(),實際上是可選的,但是React推薦加入(),這樣子就會被視為一個表示式,而不會導致
自動插入分號的問題
*/
ReactDOM.render(
element,
document.getElementById('app')
)
複製程式碼
3、JSX也是一種表示式
JSX本身也是一種表示式,所以它可以像其他表示式一樣,用於給一個變數賦值、作為函式實參、作為函式返回值,等等。如:
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}</h1>
}
return <h1>Hello, Guest!</h1>;
}
複製程式碼
注意: 1、在JSX中,宣告屬性時不要使用引號,如果宣告屬性的時候使用引號,那麼將被作為字串解析,而不會被作為一個表示式解析,如:
<div firstName="{user.firstName}" lastName={user.lastName}></div>
複製程式碼
解析後,可以得到:
<div firstName="{user.firstName}" lastName="Lau"></div>
複製程式碼
因此,當我們需要使用一個字串字面量的時候,可以使用引號,但是如果要作為表示式解析的時候,則不應當使用引號
2、在JSX中,有些屬性名稱需要進行特殊處理。如class
應該用className
代替,tabindex
則用tabIndex
代替。這是因為JSX本質上更接近於JavaScript,而class
是JavaScript中的保留字。同時,應該使用camelCase
來命名一個屬性,而不是使用HTML的屬性命名方式
3、JSX本身已經做了防注入處理,對於那些不是明確編寫的HTML程式碼,是不會被解析為HTML DOM的,ReactDOM會將他們一律視為字串,在渲染完成前就轉化為字串,所以可以防止XSS攻擊
4、如果JSX標籤是閉合的,那麼結尾需要用/>
,另外,JSX標籤是可以互相巢狀的,這和HTML裡是一樣的
4、JSX實質
JSX通過babel編譯,而babel實際上把JSX編譯給React.createElement()
呼叫。如下JSX程式碼:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
複製程式碼
是等同於以下的語句的:
const elem = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
複製程式碼
React.createElement()
方法會首先進行一些避免BUG的檢查,然後返回類似以下例子的物件:
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
}
複製程式碼
這樣的物件,則稱為React元素
,代表所有呈現在螢幕上的東西。React正是通過讀取這些物件來構建DOM,並且保持資料和UI同步的
5、元素渲染
元素(elements
)是構成React應用的最小單元,元素描述了想要在螢幕中看到的內容,如:
const element = <h1>Hello, world</h1>;
複製程式碼
和DOM元素不同的是,React元素是純物件,建立的代價低。並且React會進行優化處理,只把有必要的變化更新到DOM上。此外,元素和元件的概念,是不一樣的,元件是由元素組成的。
6、將元素渲染進DOM
在React中,使用ReactDOM.render()
方法來將React元素渲染進一個DOM中。如:
ReactDOM.render(
element,
document.getElementById('root')
)
複製程式碼
React元素是不可變的,所以一旦一個元素建立完成後,我們是無法改變其內容或者屬性的。一個元素就像是動畫裡的一幀,它代表UI在某一時間點的樣子。如果非要使用元素來構成可變化的UI介面,就需要使用setInterval
了,如:
function tick() {
const element = (
<div>Now is {new Date().toLocaleTimeString()}</div>
);
ReactDOM.render(
element,
document.getElementById('root')
);
}
setInterval(tick, 1000);
複製程式碼
在實際開發中,大多數React應用只會呼叫一次ReactDOM.render()
,所以更好的方式是使用有狀態元件
7、元件和Props
元件(component
)能夠將UI劃分為獨立的、可複用的部分,這樣我們就只需專注於構建每一個單獨的部件。
從概念上看,元件就像是函式:接受任意的輸入(稱為屬性,Props
),返回React元素。React中有兩種定義元件的方式:函式定義
和類定義
1、函式定義元件
這種方式是最簡單的定義元件的方式,就像寫一個JS函式一樣,如:
function Welcome (props) {
return <h1>Hello, {props.name}</h1>;;
}
複製程式碼
2、類定義元件
還可以使用ES6裡的類來定義一個元件,如下所示:
class Welcome extends React.Component {
render () {
return <h1>Hello, {this.props.name}<h1>;
}
}
複製程式碼
這種方式比起函式定義
方式則更加靈活
3、元件渲染
先前,我們遇到的React元素只是呈現一個DOM標籤,如:
const element = <div />
複製程式碼
然而,React元素也可以是使用者自定義的元件
,如:
const element = <Welcome name="Tom" />
複製程式碼
Welcome元件中宣告瞭一個屬性name="Tom"
,而這個屬性,將以props.name
的方式傳遞給元件,如下方式:
function Welcome (props) {
return <h1>Hello, {props.name}</h1>;
}
複製程式碼
此時,對於以下的程式碼:
ReactDOM.render(
<Welcome name="張不慫" />,
document.getElementById('root')
)
複製程式碼
最終就會以<h1>Hello, 張不慫</h1>
的方式呈現。在這個過程中,發生瞭如下的事情:
- 對
<Welcome name="張不慫" />
元素呼叫了ReactDOM.render()
豐富 - React將
{ name: '張不慫' }
作為props實參來呼叫Welcome元件 - Welcome完成渲染,返回
<h1>Hello, 張不慫</h1>
元素 - ReactDOM計算最小更新代價,然後更新DOM
4、組合元件
元件是可以組合的。即元件內部可以引用其他元件,如:
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>
標籤包裹的原因。如以下的方式,是錯誤的(因為它有3個根元素):
function App () {
return (
<Welcome name="Tom" />
<Welcome name="Jack" />
<Welcome name="Mike" />
)
}
複製程式碼
5、屬性是隻讀的
考慮以下這種情況:
function sum (a, b) {
return a + b;
}
複製程式碼
這種函式稱為純函式
:它不改變自己的輸入值,且總是對相同的輸入返回相同的結果。
與之對立的,則是非純函式
,如:
function withdraw (account, amount) {
account.total -= amount;
}
複製程式碼
非純函式
在函式內改變了輸入的引數。在React中,無論是通過function
還是class
宣告元件,我們都不應該修改它自身的屬性(props
)。雖然React相當靈活,但是它也有一個嚴格的規定:所有的React元件都必須像純函式那樣來使用它們的props
8、State與生命週期
使用類定義元件
有一些額外的好處,如擁有本地狀態
這一特性。
以下是一個類定義元件
class Clock extends React.Component {
render () {
return (
<div>
<h1>Hello, world!</h1>
<h2>Now is {this.props.date.toLocaleTimeString()}</h2>
</div>
);
}
}
複製程式碼
需要注意的有:
類名
即為元件名
(無論是函式定義元件還是類定義元件,元件名稱的首字母都必須大寫,並且繼承自React.Component
)- 使用
render()
方法,用來返回需要呈現的內容
1、在類中加入state
state是屬於一個元件自身的。我們可以在類的建構函式constructor
中來初始化狀態,如:
constructor (props) {
super(props)
this.state = {
date: new Date()
}
}
複製程式碼
如此一來,我們就可以在render()
函式中使用this.state.xxx
來引用一個狀態
2、生命週期
在應用裡,往往都會有許許多多的元件。在元件銷燬後,回收和釋放它們所佔據的資源非常重要。
在時鐘應用
的例子裡,我們需要在第一次渲染到DOM的時候設定一個定時器,並且需要在相應的DOM銷燬後,清除這個定時器。那麼,這種情況下,React為我們提供了生命週期的鉤子函式,方便我們進行使用。在React中,生命週期分為:
1)Mount
已插入真實DOM
2)Update
正在重新渲染
3)Unmount
已移出真實DOM
而相應的,生命週期鉤子函式有:
componentWillMount
componentDidMount
componentWillUpdate(newProps, nextState)
componentDidUpdate(prevProps, prevState)
componentWillUnmount()
此外,還有兩種特殊狀態的處理函式:
componentWillReceiveProps(nextProps)
已載入的元件收到新的引數時調動shouldComponentUpdate(nextProps, nextState)
元件判斷是否重新渲染時呼叫
因此,基於生命週期鉤子函式,我們可以實現一個時鐘應用如下:
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
,不應該宣告在state
裡
2)不能直接使用this.state.xxx = xxx
的方式來改變一個state
的值,應該使用this.setState()
。如:
setName () {
this.setState({
name: '張不慫'
})
}
複製程式碼
this.setState()
會自動覆蓋this.state
裡相應的屬性,並觸發render()
重新渲染。
3)狀態更新可能是非同步的
React可以將多個setState()
呼叫合併成一個呼叫來提升效能。且由於this.props
和this.state
可能是非同步更新的,所以不應該依靠它們的值來計算下一個狀態。這種情況下,可以給setState
傳入一個函式,如:
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
複製程式碼
9、事件處理
React元素的事件與DOM元素類似,不過也有一些區別,如:
1)React事件使用camelCase
命名(onClick
),而不是全小寫的形式(onclick
)
2)使用JSX,傳入的是事件的控制程式碼,而不是一個字串
如以下的HTML:
<button onclick="increment()">ADD</button>
複製程式碼
使用React的方式描述如:
<button onClick={increment}>ADD</button>
複製程式碼
還有一個不同在於,在原生DOM中,我們可以通過返回false
來阻止預設行為,但是這在React中是行不通的,在React中需要明確使用preventDefault()
來阻止預設行為。如:
function ActionLink () {
function handleClick (e) {
e.preventDefault();
alert('Hello, world!');
}
return (
<a href="#" onClick={handleClick}>Click Me</a>
);
}
複製程式碼
這裡,事件回撥函式裡的event
是經過React特殊處理過的(遵循W3C標準),所以我們可以放心地使用它,而不用擔心跨瀏覽器的相容性問題。
注意: 在使用事件回撥函式的時候,我們需要特別注意this
的指向問題,因為在React裡,除了建構函式和生命週期鉤子函式裡會自動繫結this為當前元件外,其他的都不會自動繫結this
的指向為當前元件,因此需要我們自己注意好this的繫結問題,
通常而言,在一個類方式宣告的元件裡使用事件回撥,我們需要在元件的constructor
裡繫結回撥方法的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>
);
}
}
複製程式碼
當然,我們還有另外一種方法來使用箭頭函式繫結指向,就是使用實驗性
的屬性初始化語法,如:
class Counter extends React.Component {
increment: () => {
this.setState({
counter: this.state.counter + 1
});
}
// ...
}
複製程式碼
3)像事件處理程式傳遞引數 我們可以為事件處理程式傳遞額外的引數,方式有以下兩種:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
複製程式碼
需要注意的是,使用箭頭函式的情況下,引數e
要顯式傳遞,而使用bind的情況下,則無需顯式傳遞(引數e
會作為最後一個引數傳遞給事件處理程式)
10、條件渲染
在React裡,我們可以建立不同的元件來封裝我們需要的功能。我們也可以根據元件的狀態,只渲染元件中的一部分內容,而條件渲染就是為此而準備的。在React中,我們可以像在JavaScript中寫條件語句一樣地寫條件渲染語句,如:
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、使用變數來儲存元素
我們也可以使用變數來儲存元素,如:
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、使用&&運算子進行渲染
由於JavaScript語法對待&&
運算子的性質,我們也可以使用&&運算子來完成條件渲染,如:
function LogBtn(props) {
var button;
const isLogined = props.isLogined;
return (
<div>Hello
{!isLogined && (
<button>請登陸</button>
)}
</div>
)
}
複製程式碼
當props.isLogined
為false的時候,就會渲染出:
<div>Hello <button>請登入</button></div>
複製程式碼
3、使用三目運算子進行渲染
我們可能已經發現了,其實JSX可以像一個表示式那樣子靈活使用,所以,我們自然也可以使用三目運算子進行渲染,如:
function LogBtn (props) {
const isLogined = props.isLogined;
return (
<div>You can
<button>{isLogined ? '退出' : '登陸'}</button>
</div>
)
}
複製程式碼
4、阻止整個元件的渲染
有時候,我們希望是整個元件都不渲染,而不僅僅是區域性不渲染,那麼這種情況下,我們就可以在render()
函式裡返回一個null
,來實現我們想要的效果,如:
function LogBtn (props) {
const isLogined = props.isLogined;
const isShow = props.isShow;
if (isShow) {
return (
<div>You can
<button>{isLogined ? '退出' : '登陸'}</button>
</div>
)
}
return null;
}
複製程式碼
注意: 元件裡返回null
不會影響元件生命週期的觸發,如componentWillUpdate
和componentDidUpdate
仍然會被呼叫
11、列表渲染與keys
在JavaScript中,我們可以使用map()
函式來對一個陣列列表進行操作,如:
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(number => number*2);
console.log(doubled); // 得到[2, 4, 6, 8, 10]
複製程式碼
同樣的,在React裡,我們也可以使用map()
來進行列表渲染,如:
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>
複製程式碼
當然,我們還可以進行更好的封裝,如:
function NumberList (props) {
const numbers = props.numbers;
const listItems = numbers.map(number => {
return (
<li>{number}</li>
)
});
return <ul>{listItems}</ul>
}
複製程式碼
當我們執行以上的程式碼的時候,會發現控制檯提示:Each child in an array or iterator should have a unique "key" prop
,因此,我們需要為列表項的每一個項分配一個key
,來解決這個問題,通常而言,我們可以使用以下幾種方式來提供key
:
- 使用資料項自身的ID,如
<li key={item.itemId}>
- 使用索引下標(
index
),如:
const listItems = numbers.map((number, index) => {
<li key={index}>{number}</li>
});
複製程式碼
但是React不推薦在需要重新排序的列表裡使用索引下標,因為會導致變得很慢。
注意: 只有在一個項的同胞裡區分彼此的時候,才需要使用到key,key不需要全域性唯一,只需要在一個陣列內部區分彼此時唯一便可。key的作用是給React一個提示,而不會傳遞給元件。如果我們在元件內需要同樣的一個值,可以換個名字傳遞,如:
const content = posts.map(post => (
<Post key={post.id} id={post.id} title={post.title} />
));
複製程式碼
12、表單
表單和其他的React中的DOM元素有所不同,因為表單元素生來就是為了儲存一些內部狀態。在React中,表單和HTML中的表單略有不同
1、受控元件
HTML中,<input>
、<textarea>
、<select>
這類表單元素會維持自身狀態,並根據使用者輸入進行更新。不過React中,可變的狀態通常儲存在元件的this.state
中,且只能用setState()
方法進行更新,如:
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
並不需要寫成<textarea></textarea>
的形式,而是寫成<textarea value="" ... />
的形式便可。而對於HTML中的select
標籤,通常做法是:
<select>
<option value="A">A</option>
<option value="B" selected>B</option>
<option value="C">C</option>
</select>
複製程式碼
但是React中,不需要在需要選中的option
處加入selected
,而只需要傳入一個value,就會自動根據value來選中相應的選項,如:
<select value="C">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
複製程式碼
那麼如上述例子,C所在的這個option
就會被選中
2、多個輸入的解決辦法
通常一個表單都有多個輸入,如果我們為每一個輸入新增處理事件,那麼將會非常繁瑣。好的一個解決辦法是,使用name,然後根據event.target.name
來選擇做什麼。如:
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 ? '參加' : '不參加'}活動`
});
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>您的報名資訊:{this.state.profile}</p>
</form>
)
}
}
複製程式碼
3、非受控元件
大多數情況下,使用受控元件
實現表單是首選,在受控元件中,表單資料是交由React元件處理的。如果想要讓表單資料由DOM處理(即資料不儲存在React的狀態裡,而是儲存在DOM中),那麼可以使用非受控元件
,使用非受控元件
,可以無需為每個狀態更新編寫事件處理程式,使用ref
即可實現,如:
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>
)
}
}
複製程式碼
對於非受控元件
,如果要指定預設值,那麼可以使用defaultValue
,如:
<input type="text" defaultValue="Hello" ref={input => this.input = input} />
複製程式碼
相應的,type="checkbox"
和type="radio"
,則使用defaultChecked
13、狀態提升
當需要幾個元件共用狀態資料的時候,可以使用狀態提升技術。核心思想在於:把資料抽離到最近的共同父元件,父元件管理狀態(state),然後通過屬性(props)傳遞給子元件。如實現一個貨幣轉換的元件,可以如下:
1、首先定義轉換函式
function USD2RMB (amount) {
return amount * 6.7925;
}
function RMB2USD (amount) {
return amount * 0.1472;
}
function convert (amount, typeFn) {
return typeFn(amount);
}
複製程式碼
2、定義元件
我們希望在RMB的輸入表單上上輸入的時候,USD的輸入表單上的數值也同步更新,這種情況下,如果RMB元件自己管理自己的狀態,是很難以實現的,因此,我們需要讓這個狀態提升自父元件進行管理。如下:
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>
);
}
}
複製程式碼
最後定義一個共同的父元件,如下:
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推崇更多的是使用組合,而非使用繼承。對於一些使用場景,React給出的建議如下:
1、包含關係
當父元件不知道子元件可能的內容是什麼的時候,可以使用props.children
,如:
function Article (props) {
return (
<section>
<aside>側邊欄</aside>
<article>{props.children}</article>
</section>
);
}
function App () {
return (
<Article>這是一篇文章</Article>
);
}
複製程式碼
這將渲染得到:
<section>
<aside>側邊欄</aside>
<article>這是一篇文章</article>
</section>
複製程式碼
我們還可以自定義名稱,因為JSX實際上會被轉化為合法的JS表示式,所以,還可以有:
function Article (props) {
return (
<section>
<aside>{props.aside}</aside>
<article>{props.children}</article>
</section>
);
}
function App () {
return (
<Article aside={
<h1>這是一個側欄</h1>
}>這是一篇文章</Article>
);
}
複製程式碼
這將渲染得到:
<section>
<aside><h1>這是一個側欄</h1></aside>
<article>這是一篇文章</article>
</section>
複製程式碼
2、何時使用繼承?
在Facebook的網站上,使用了數以千計的元件,但是實踐證明還沒有發現需要使用繼承才能解決的情況。 屬性和組合為我們提供了清晰的、安全的方式來自定義元件的樣式和行為,元件可以接受任意元素,包括:基本資料型別、React元素、函式。 如果要在元件之間複用UI無關的功能,那麼應該將其提取到單獨的JavaScript模組中,這樣子可以在不對元件進行擴充套件的前提下匯入並使用函式、物件、類
覺得對你有幫助,不妨點個
贊,
不妨再點個關注,不迷路,下一篇關於redux的明天就發!!~