其中標紅的( componentWillMount、 componentWillReceiveProps、 componentWillUpdate )是 react 16.3 版本要移除的生命週期,移除緣由:react 打算在17版本中,添加 async rendering , react 將一個更新過程分爲 render 先後兩個階段,render 前是能夠被打斷(好比有緊急任務),當生命週期被打斷後,再次執行,並不會從斷點繼續執行,是從新執行的,因此這些生命週期就可能會運行屢次。html
同時爲了彌補失去這三個生命,react 新增了兩個生命週期: static getDerivedStateFromProps、 getSnapshotBeforeUpdatereact
getDerivedStateFromProps 會在調用 render 方法以前調用,而且在初始掛載及後續更新時都會被調用。它應返回一個對象來更新 state,若是返回 null 則不更新任何內容。算法
此方法適用於罕見的用例,即 state 的值在任什麼時候候都取決於 props。編程
static getDerivedStateFromProps(nextProps, prevState) {
//根據nextProps和prevState計算出預期的狀態改變,返回結果會被送給setState
//這是一個static,簡單說應該是一個純函數
}
複製代碼
getSnapshotBeforeUpdate() 在最近一次渲染輸出(提交到 DOM 節點)以前調用。它使得組件能在發生更改以前從 DOM 中捕獲一些信息(例如,滾動位置)。今生命週期的任何返回值將做爲參數傳遞給 componentDidUpdate()。api
getSnapshotBeforeUpdate 返回的值會作爲第三個參數傳遞給 componentDidUpdate。數組
getSnapshotBeforeUpdate(prevProps, prevState) {
...
return snapshot;
}
componentDidUpdate(prevProps, prevState, snapshot) {
}
複製代碼
這是一個組件的子樹。每一個節點中,SCU 表明 shouldComponentUpdate 返回的值,而 vDOMEq 表明返回的 React 元素是否相同。最後,圓圈的顏色表明了該組件是否須要更新。性能優化
react 父組件觸發更新時,它的全部子組件都會觸發更新(即便 props 和 state )並無改變,這樣時候咱們在子組件中添加 shouldComponentUpdate 生命週期,判斷狀態是否變動,若是沒有變動返回 false , 這個子組件就不會從新 render。markdown
React.PureComponent 是 React 自動幫咱們在 shouldComponentUpdate 作了一層淺比較。app
if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps)
|| !shallowEqual(inst.state, nextState);
}
複製代碼
React.memo 是一個高階組件,相似於 React.PureComponent,不一樣於 React.memo 是 function 組件,React.PureComponent 是 class 組件。dom
const MyComponent = React.memo(function MyComponent(props) {
/* 使用 props 渲染 */
});
複製代碼
key 幫助 React 識別哪些元素改變了,好比被添加或刪除。當子元素擁有 key 時,React 使用 key 來匹配原有樹上的子元素以及最新樹上的子元素。正確的使用 key 可使 react 的更新開銷變小。
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
複製代碼
概念:將公用方法包裝成 Mixin 方法,而後注入各個組件,從而實現代碼複用。( 已經不推薦 )
缺點:
概念:能夠理解爲組件工廠,傳入原始組件,添加功能,返回新的組件。
缺點:
概念:Render Props 就是一個 render 函數做爲 props 傳遞給了父組件,使得父組件知道如何渲染子組件。
優勢:
缺點:
概念:hooks 遵循函數式編程的理念,主旨是在函數組件中引入類組件中的狀態和生命週期,而且這些狀態和生命週期函數也能夠被抽離,實現複用的同時,減小函數組件的複雜性和易用性。
hooks api:
一個簡單的 custom hooks:
import { useEffect } from 'react';
function useTitle(title){
useEffect(()=>{
document.title = title;
}, [title]);
}
複製代碼
虛擬 Dom:react 將 Dom 抽象成一個對象樹,經過對比新舊兩個樹的區別(diff 算法),而後將更新部分渲染出來。
diff 算法基於兩個策略:
在 react 中,樹的比對很是簡單,react 只會對兩棵樹進行逐層比較,即比較處於同一層級的節點。
節點比較分紅兩種狀況:(1)節點類型不一樣,(2)節點類型相同,屬性不一樣。
狀況(1):
// DOM Diff 操做
C.destroy();
D = new D();
A.append(D);
複製代碼
狀況(2):
//變動錢
<div style={{fontSize: '16px'}} ></div>
//變動後
<div style={{color: 'red'}} ><div/> //執行操做 => removeStyle fontSize => addStyle color 'red' 複製代碼
當列表中插入 F 節點,以下圖:
這個時候就會有兩種狀況:(1)節點沒有表示惟一 key ,(2)節點表示了惟一 key
狀況(1)結果以下圖:
//執行過程
C unmount
D unmount
E unmount
F mount
C mount
D mount
E mount
複製代碼
狀況(2)結果以下圖:
//執行過程
F mount
複製代碼
若是在組件的渲染或生命週期方法中引起錯誤,整個組件結構就會從根節點中卸載,而不影響其餘組件的渲染,能夠利用 error boundaries 進行錯誤的優化處理。
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
複製代碼
react 支持將組建掛在到其餘 dom 節點,事件仍是按組件原有位置冒泡。
render() {
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}
複製代碼
Fiber 是對 react 核心算法 reconciliation 的更新實現,將本來的同步更新分紅兩個階段。階段1(Reconciliation Phase)的任務是片斷化執行的,每一個片斷執行完成以後,就會把控制權從新交給 react 調度模塊,若是有更高優先級的任務就去處理,而低優先級更新任務所作的工做則會徹底做廢,而後等待機會重頭再來,若是沒有就執行下一個片斷。階段2(Commit Phase)是同步執行的,reactDom 會根據階段1計算出來的 effect-list 來更新 DOM 。
階段1涉及的生命週期(可能會執行屢次):componentWillMount、 componentWillReceiveProps、 shouldComponentUpdate、 componentWillUpdate
階段2涉及的生命週期:componentDidMount、 componentDidUpdate、 componentWillUnmount
全新的 Context API 能夠很容易實現祖先節點和子節點通訊,而且沒有反作用。
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
state = {theme: 'light'};
render() {
return (
<ThemeContext.Provider value={this.state.theme}> {this.props.children} </ThemeContext.Provider>
);
}
}
class ThemedButton extends React.Component {
render() {
return (
<ThemeContext.Consumer> {theme => <Button theme={theme} />} </ThemeContext.Consumer>
);
}
}
複製代碼
React.lazy() 提供了動態 import 組件的能力,實現代碼分割。
Suspense 做用是在等待組件時 suspend(暫停)渲染,並顯示加載標識。
import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense>
);
}
複製代碼