一、首先我們先看一下類(class)組件整個周期包含哪些:
class MyComponent extends Component { // ======= 掛載卸載階段 constructor(props: any) { super(props); this.state = { name: 'Hello World', }; } // 16.8 新增鈎子函數 static getDerivedStateFromProps(props, state) { console.log('判斷數據是否需要更新', props, state); return null; } // 16.8 已廢棄 componentWillMount() { console.log('渲染之前'); } // 16.8 componentWillMount變更,后續可能會廢棄 UNSAFE_componentWillMount() { console.log('渲染之前'); } render() { console.log('渲染'); return <div>MyComponent</div>; } componentDidMount() { console.log('渲染完成'); } // ==========更新階段,也會重新調用getDerivedStateFromProps // 16.8 新增鈎子函數 static getDerivedStateFromProps(props, state) { console.log('判斷數據是否需要更新', props, state); return null; } // 16.8已廢棄 componentWillReceiveProps(nextProps) { console.log('接收到來自父組件的數據', nextProps); } // 16.8 componentWillReceiveProps變更而來 UNSAFE_componentWillReceiveProps(nextProps) { console.log('接收到來自父組件的數據', nextProps); } // 16.8新增鈎子函數 static getSnapshotBeforeUpdate(prevProps, prevState) { console.log('返回組件更新daom', prevProps, prevState); } shouldComponentUpdate(nextProps, nextState) { console.log('判斷數據是否更新true,false來判斷', nextProps, nextState); return false; } // 16.8已廢棄 componentWillUpdate(nextProps, nextState) { console.log('組件數據將要更新', nextProps, nextState); } // 16.8 變更componentWillUpdate UNSAFE_componentWillUpdate(nextProps, nextState) { console.log('組件數據將要更新', nextProps, nextState); } componentDidUpdate(prevProps) { console.log('組件數據更新完畢', prevProps); } // ========= 卸載階段 componentWillUnmount() { console.log('已經銷毀'); } // 其他api static getDerivedStateFromError(error) { // 更新 state 使下一次渲染可以顯示降級 UI return { hasError: true }; } componentDidCatch(error, info) { // 捕獲錯誤信息 } // 增加錯誤信息校驗 render() { if (this.state.hasError) { // 你可以渲染任何自定義的降級 UI return <h1>Something went wrong.</h1>; } return this.props.children; } }
1、constructor:
構造函數,如不初始化state或者進行函數綁定,可以不進行react組件實現構造函數;通過在構造函數中初始化state,接受來自父組件的props
2、getDerivedStateFromProps:
16.8之后的一個靜態方法,通過接受父組件props判斷是否執行更新,返回null不更新,具體見另外一篇文章分析,詳見react16.8 新的生命周期
3、componentWillMount(已過時) => UNSAFE_compomentWillMount
react 16.8之前的周期函數,在render之前調用,所有setState不會出來額外渲染,組件dom節點沒有渲染之前進行加載一些數據,一般進行服務端渲染的時候進行優化,16.8以后改為UNSAFE_compomentWillMount,但是沒有被廢棄,保留原來的函數;
4、render:
一個純渲染函數,返回Dom,React組件,Fragment等
5、componentDidMount:
組件掛載時調用,此時dom已渲染,可以獲取canvas,svg等操作,可以進行數據操作,獲取接口數據;
6、componentWillReceiveProps(已過時) => UNSAFE_componentWillReceiveProps
組件掛載階段接受父組件props參數進行state更新操作,需要妥善處理,不然容易循環渲染等問題,16.8以后被getDerivedStateFromProps替換;
7、getSnapshotBeforeUpdate:
16.8以后的一個靜態方法,判斷dom節點更新階段更新時,及時獲取更新后的dom節點,同樣進行單獨的分析,詳見 react16.8 新的生命周期
8、shouldComponentUpdate:
一個比較重要的周期,在組件更新階段是否執行更新操作,默認返回false不重新渲染,返回true重新渲染,根據props和state的進行比較是否進行節點更新操作,component和pureComponent區別就在於此
9、componentWillUpdate (已過時)=> UNSAFE_compinetWillUpdate
16.8已廢棄,更新階段獲取更新后的dom節點,為更新階段做准備;
10、componentDidUpdate:
組件更新階根據返回的參數props,state,snapshot,第三個參數是之前getSnapshotBeforeUpdate返回的,如果出來函數毀掉時需要Dom元素的狀態,則將對比計算機的過程遷移至getSanapShotBeforeUpdate,然后在componentDidUpdate中統一觸發更新;
11、componentWillUnmount:
我們組件卸載階段執行的方法,組件銷毀進行執行初始化的一些操作;
12、getDeriedStateFromError和componentDidCatch
錯誤捕獲日志,我們可以根據我們錯誤信息進行捕獲,增加錯誤邊界等組件進行1前端代碼兼容
二、然后我們再看看無狀態(hooks)組件的鈎子函數
const MyComponent = React.memo((props) =>{
React.useMemo(() => ()=>{ console.log('組件dom節點沒有渲染之前調用一次'); }, []); const renderDom = React.useMemo(() => ()=>{ console.log('組件dom節點沒有渲染之前根據依賴參數props調用'); }, [props]) React.useEffect(() => { console.log('組件初始化調用一次'); }, []) React.useEffect(()=>{ console.log('組件根據依賴參數props更新調用'); },[props]) React.useEffect(()=>{ return ()=>{ console.log('組件卸載調用'); } },[]); const handleClick = React.useCallback(() =>{ console.log('監聽事件通過鈎子函數包裹,優化性能'); },[]); return ( console.log('返回dom節點'); ) });
1、useState:
和class的state類似,只不過是獨立管理組件變量,
2、useMemo:
組件Dom節點,進行計算一些,包括要渲染的Dom或者數據,根據依賴參數進行更新
3、useEffect:
hooks的組件生命周期其實就是鈎子函數useEffect的不同用法,傳遞參數的不同會導致不同的結果,具體分析見React.useEffect參數不同
4、useCallBack:
一個鈎子函數,通過包裹我們的普通函數進行性能優化;
后面繼續完善