一. setState
setState更新狀態(tài)的2種寫法
(1). setState(stateChange, [callback])------對象式的setState
1.stateChange為狀態(tài)改變對象(該對象可以體現(xiàn)出狀態(tài)的更改)
2.callback是可選的回調(diào)函數(shù), 它在狀態(tài)更新完畢、界面也更新后(render調(diào)用后)才被調(diào)用
(2). setState(updater, [callback])------函數(shù)式的setState
1.updater為返回stateChange對象的函數(shù)厚棵。
2.updater可以接收到state和props柑潦。
4.callback是可選的回調(diào)函數(shù), 它在狀態(tài)更新杂拨、界面也更新后(render調(diào)用后)才被調(diào)用唧躲。
總結(jié):
1.對象式的setState是函數(shù)式的setState的簡寫方式(語法糖)
2.使用原則:
(1).如果新狀態(tài)不依賴于原狀態(tài) ===> 使用對象方式
(2).如果新狀態(tài)依賴于原狀態(tài) ===> 使用函數(shù)方式
(3).如果需要在setState()執(zhí)行后獲取最新的狀態(tài)數(shù)據(jù),
要在第二個callback函數(shù)中讀取
二. lazyLoad
路由組件的lazyLoad
//1.通過React的lazy函數(shù)配合import()函數(shù)動態(tài)加載路由組件 ===> 路由組件代碼會被分開打包
const Login = lazy(()=>import('@/pages/Login'))
//2.通過<Suspense>指定在加載得到路由打包文件前顯示一個自定義loading界面
<Suspense fallback={<h1>loading.....</h1>}>
<Switch>
<Route path="/xxx" component={Xxxx}/>
<Redirect to="/login"/>
</Switch>
</Suspense>
三. Hooks
1. React Hook/Hooks是什么?
(1). Hook是React 16.8.0版本增加的新特性/新語法
(2). 可以讓你在函數(shù)組件中使用 state 以及其他的 React 特性
2. 三個常用的Hook
(1). State Hook: React.useState()
(2). Effect Hook: React.useEffect()
(3). Ref Hook: React.useRef()
3. State Hook
(1). State Hook讓函數(shù)組件也可以有state狀態(tài), 并進行狀態(tài)數(shù)據(jù)的讀寫操作
(2). 語法: const [xxx, setXxx] = React.useState(initValue)
(3). useState()說明:
參數(shù): 第一次初始化指定的值在內(nèi)部作緩存
返回值: 包含2個元素的數(shù)組, 第1個為內(nèi)部當前狀態(tài)值, 第2個為更新狀態(tài)值的函數(shù)
(4). setXxx()2種寫法:
setXxx(newValue): 參數(shù)為非函數(shù)值, 直接指定新的狀態(tài)值, 內(nèi)部用其覆蓋原來的狀態(tài)值
setXxx(value => newValue): 參數(shù)為函數(shù), 接收原本的狀態(tài)值, 返回新的狀態(tài)值, 內(nèi)部用其覆蓋原來的狀態(tài)值
4. Effect Hook
(1). Effect Hook 可以讓你在函數(shù)組件中執(zhí)行副作用操作(用于模擬類組件中的生命周期鉤子)
(2). React中的副作用操作:
發(fā)ajax請求數(shù)據(jù)獲取
設(shè)置訂閱 / 啟動定時器
手動更改真實DOM
(3). 語法和說明:
useEffect(() => {
// 在此可以執(zhí)行任何帶副作用操作
return () => { // 在組件卸載前執(zhí)行
// 在此做一些收尾工作, 比如清除定時器/取消訂閱等
}
}, [stateValue]) // 如果指定的是[], 回調(diào)函數(shù)只會在第一次render()后執(zhí)行
(4). 可以把 useEffect Hook 看做如下三個函數(shù)的組合
componentDidMount()
componentDidUpdate()
componentWillUnmount()
5. Ref Hook
(1). Ref Hook可以在函數(shù)組件中存儲/查找組件內(nèi)的標簽或任意其它數(shù)據(jù)
(2). 語法: const refContainer = useRef()
(3). 作用:保存標簽對象,功能與React.createRef()一樣
四. Fragment
使用
<Fragment><Fragment>
<></>
作用
可以不用必須有一個真實的DOM根標簽了
五. Context
理解
一種組件間通信方式, 常用于【祖組件】與【后代組件】間通信
使用
1) 創(chuàng)建Context容器對象:
const XxxContext = React.createContext()
2) 渲染子組時,外面包裹xxxContext.Provider, 通過value屬性給后代組件傳遞數(shù)據(jù):
<xxxContext.Provider value={數(shù)據(jù)}>
子組件
</xxxContext.Provider>
3) 后代組件讀取數(shù)據(jù):
//第一種方式:僅適用于類組件
static contextType = xxxContext // 聲明接收context
this.context // 讀取context中的value數(shù)據(jù)
//第二種方式: 函數(shù)組件與類組件都可以
<xxxContext.Consumer>
{
value => ( // value就是context中的value數(shù)據(jù)
要顯示的內(nèi)容
)
}
</xxxContext.Consumer>
注意
在應用開發(fā)中一般不用context, 一般都用它的封裝react插件
六. 組件優(yōu)化
Component的2個問題
只要執(zhí)行setState(),即使不改變狀態(tài)數(shù)據(jù), 組件也會重新render() ==> 效率低
只當前組件重新render(), 就會自動重新render子組件锦针,縱使子組件沒有用到父組件的任何數(shù)據(jù) ==> 效率低
效率高的做法
只有當組件的state或props數(shù)據(jù)發(fā)生改變時才重新render()
原因
Component中的shouldComponentUpdate()總是返回true
解決
辦法1:
重寫shouldComponentUpdate()方法
比較新舊state或props數(shù)據(jù), 如果有變化才返回true, 如果沒有返回false
辦法2:
使用PureComponent
PureComponent重寫了shouldComponentUpdate(), 只有state或props數(shù)據(jù)有變化才返回true
注意:
只是進行state和props數(shù)據(jù)的淺比較, 如果只是數(shù)據(jù)對象內(nèi)部數(shù)據(jù)變了, 返回false
不要直接修改state數(shù)據(jù), 而是要產(chǎn)生新數(shù)據(jù)
項目中一般使用PureComponent來優(yōu)化
七. render props
如何向組件內(nèi)部動態(tài)傳入帶內(nèi)容的結(jié)構(gòu)(標簽)?
Vue中:
使用slot技術(shù), 也就是通過組件標簽體傳入結(jié)構(gòu) <A><B/></A>
React中:
使用children props: 通過組件標簽體傳入結(jié)構(gòu)
使用render props: 通過組件標簽屬性傳入結(jié)構(gòu),而且可以攜帶數(shù)據(jù)弟蚀,一般用render函數(shù)屬性
children props
<A>
<B>xxxx</B>
</A>
{this.props.children}
問題: 如果B組件需要A組件內(nèi)的數(shù)據(jù), ==> 做不到
render props
<A render={(data) => <C data={data}></C>}></A>
A組件: {this.props.render(內(nèi)部state數(shù)據(jù))}
C組件: 讀取A組件傳入的數(shù)據(jù)顯示 {this.props.data}
八. 錯誤邊界
理解:
錯誤邊界(Error boundary):用來捕獲后代組件錯誤,渲染出備用頁面
特點:
只能捕獲后代組件生命周期產(chǎn)生的錯誤挑豌,不能捕獲自己組件產(chǎn)生的錯誤和其他組件在合成事件安券、定時器中產(chǎn)生的錯誤
使用方式:
getDerivedStateFromError配合componentDidCatch
// 生命周期函數(shù),一旦后臺組件報錯氓英,就會觸發(fā)
static getDerivedStateFromError(error) {
console.log(error);
// 在render之前觸發(fā)
// 返回新的state
return {
hasError: true,
};
}
componentDidCatch(error, info) {
// 統(tǒng)計頁面的錯誤侯勉。發(fā)送請求發(fā)送到后臺去
console.log(error, info);
}
九. 組件通信方式總結(jié)
組件間的關(guān)系:
- 父子組件
- 兄弟組件(非嵌套組件)
- 祖孫組件(跨級組件)
幾種通信方式:
1.props:
(1).children props
(2).render props
2.消息訂閱-發(fā)布:
pubs-sub、event等等
3.集中式管理:
redux债蓝、dva等等
4.conText:
生產(chǎn)者-消費者模式
比較好的搭配方式:
父子組件:props
兄弟組件:消息訂閱-發(fā)布壳鹤、集中式管理
祖孫組件(跨級組件):消息訂閱-發(fā)布、集中式管理饰迹、conText(開發(fā)用的少芳誓,封裝插件用的多)