前言
- react官方是沒給像vue那種keep-alive功能的,網上有些大佬寫了些庫,裏面涉及的東西有點多。我感覺這玩意也可以自己搞個簡陋版本,滿足自己需要就行。
原理
- react-router在對路由匹配時,不匹配的就直接卸載了。所以爲了成爲常駐組件,就不能讓Route來進行匹配渲染。
- 那麼就解決了卸載問題,但又出現3個問題:
- 一、如何控制組件顯示與消失?
- 二、如何匹配路由?
- 三、如何解決傳值刷新?
- 對於第一個問題,就是你可以進行display的動態切換來進行渲染。並且這樣的切換,子組件不會卸載。
- 對於第二個問題,一般來說,我們都會使用connected-react-router的中間件,將history傳給它,作爲store的狀態,這樣就可以通過store很方便的取到當前匹配的路徑,然後對路徑進行判斷就可以了。
- 對於第三個問題,其實正常來說,只要有值改變,我們做的keepAlive組件加上裏面的子組件全都會刷新,因爲使用store一般都會結合connect,當store裏面狀態發生改變,connect的組件所收到的props就會發生改變,而組件的props改變,會導致組件的刷新。但它確實不會卸載。我們可以通過useEffect加上一個空數組依賴來測試它。
- 當然,爲了優化傳值,我們可能有必要在KeepAlive組件裏對每個子組件需要什麼參數進行整理。
代碼
- 我通過useEffect加空數組的方法看是否卸載。
function KeepAlive(props:Props) {
console.log(props)
useEffect(()=>{
console.log('我執行了KeepAlive')
},[])
useMemo(()=>({}),[props.cart])
return(
<>
<div style={{display:props.router.location.pathname=='/cart'?'block':'none'}}>
cart
<KKK cart ={props.cart}></KKK>
</div>
<div style={{display:props.router.location.pathname=='/profile'?'block':'none'}}>
profile
</div>
</>
)
}
const mapStateToProps=(state: CombinedState):CombinedState=>(state)
export default connect(mapStateToProps)(KeepAlive)
function Subcop(params:{cart:CartState}) {
console.log('xuanr')
console.log(params.cart)
useEffect(()=>{
console.log('我執行了Subcop')
},[])
return(
<div >xxxxxxxxx</div>
)
}
let KKK = React.memo(Subcop)
- 我順便試了下,子組件用React.lazy進行懶加載代碼分割也是完全ok,只有第一次出現的時候network會飄來腳本,然後就變成常駐組件。