有段時間,這個問題標準回答是 class 組件提供了訪問更多特性的權限(好比state),隨着 Hooks 發佈,那就不是這樣了。javascript
或許,你聽過他們中哪一個性能更好這樣的問題,性能取決於你的代碼作了什麼而不是你選擇用 function 仍是class 組件。實際上這二者之間的性能差異是微不足道的,具體能夠參考這個對比結果。html
在這篇文章中,咱們來看看它們二者之間最大的不一樣。java
事先申明:並不對 Function 與 Classes 進行優劣對比,而僅僅是說明 react 兩種模式的不一樣。react
對比下面兩段代碼:git
Function Component:github
function ProfilePage(props) {
const showMessage = () => {
alert("Followed " + props.user);
};
const handleClick = () => {
setTimeout(showMessage, 3000);
};
return <button onClick={handleClick}>Follow</button>;
}複製代碼
Class Component:ide
class ProfilePage extends React.Component {
showMessage = () => {
alert("Followed " + this.props.user);
};
handleClick = () => {
setTimeout(this.showMessage, 3000);
};
render() {
return <button onClick={this.handleClick}>Follow</button>;
}複製代碼
這兩個組件代碼都描述了同一個邏輯:點擊按鈕 3 秒後 alert
父級傳入的用戶名。經過這個 在線 Demo 完整代碼,執行如下操做來講明二者的區別:函數
咱們能夠看到:性能
Class Component 展現的是修改後的值this
Function Component 展現的是修改前的值:
這個例子中function 組件展現的纔是咱們指望的結果,由於我點了 follow 不但願因父級 props變化而改變本來指望的渲染結果,爲何 class 組件例子中出現這種狀況?
class ProfilePage extends React.Component {
showMessage = () => {
alert("Followed " + this.props.user);
};複製代碼
緣由是在 react 中 props 不可變(Immutable) 數據,可是在 react class 組件中,this 是可變的,所以 this.props
的調用會致使每次都訪問最新的 props
。上面的 showMessage 是在3秒後執行,這時props是最新的。而 Function Component 不存在 this.props
的語法,所以 props
老是不可變的。
如何解決這個問題?
一種方式是在事件綁定方法中讀取這個 props
,而後傳遞給showMessage:
class ProfilePage extends React.Component {
showMessage = (user) => {
alert('Followed ' + user);
};
handleClick = () => {
const {user} = this.props;
setTimeout(() => this.showMessage(user), 3000);
};
render() {
return <button onClick={this.handleClick}>Follow</button>;
}
}複製代碼
可是這樣寫代碼顯得臃腫囉嗦,並且,若是在showMessage中要調用其餘方法,這個方法又要讀取 this.props.somthing
或者 this.state.someting
又要傳遞this.props 或者 this.state,這樣就很麻煩。
另外一種方式就是在 render 函數中讀取props:
class ProfilePage extends React.Component {
render() {
// Capture the props!
const props = this.props;
// Note: we are *inside render*.
// These aren't class methods.
const showMessage = () => {
alert('Followed ' + props.user);
};
const handleClick = () => {
setTimeout(showMessage, 3000);
};
return <button onClick={handleClick}>Follow</button>;
}
}複製代碼
這看起來很奇怪,加以簡化,其實就是 function 組件。
看下面代碼:
function MessageThread() {
const [message, setMessage] = useState('');
const showMessage = () => {
alert('You said: ' + message);
};
const handleSendClick = () => {
setTimeout(showMessage, 3000);
};
const handleMessageChange = (e) => {
setMessage(e.target.value);
};
return (
<>
<input value={message} onChange={handleMessageChange} />
<button onClick={handleSendClick}>Send</button>
</>
);
}複製代碼
在點擊 Send
按鈕後,再次修改輸入框的值,3 秒後的輸出依然是 點擊前輸入框的值。這說明 Hooks 一樣具備 capture value 的特性。
若是咱們想避開 capture values 的特性,就想獲取最新的輸入框的值怎麼辦?在 class 組件中,咱們只須要訪問 this.props 就行,由於 this 是可變的,能讀取最新的props。
這裏咱們利用 useRef
能夠規避 capture values 特性:
function MessageThread() {
const [message, setMessage] = useState('');
// Keep track of the latest value.
const latestMessage = useRef('');
useEffect(() => {
latestMessage.current = message;
});
const showMessage = () => {
alert('You said: ' + latestMessage.current);
};
const handleSendClick = () => {
setTimeout(showMessage, 3000);
};
const handleMessageChange = (e) => {
setMessage(e.target.value);
};
return (
<>
<input value={message} onChange={handleMessageChange} />
<button onClick={handleSendClick}>Send</button>
</>
);
}複製代碼
function 組件與 class 組件最大的不一樣是 function 組件可以捕獲渲染的值,而 class 組件由於 react 中 this 是可變的,因此老是能獲取最新的 props 。一樣 hooks 和 function 組件同樣具備 capture values 特性,利用useRef 能夠避免 capture values 特性。