最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用react-activation實(shí)現(xiàn)keepAlive支持返回傳參

 更新時(shí)間:2022年05月18日 11:29:44   作者:佟舟  
本文主要介紹了使用react-activation實(shí)現(xiàn)keepAlive支持返回傳參,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

介紹

這個(gè)項(xiàng)目是一個(gè)商城的后臺(tái)管理系統(tǒng),用umi2.0搭建,狀態(tài)管理使用dva,想要實(shí)現(xiàn)類似vue keep-alive的效果。

具體表現(xiàn)為:

從列表頁(yè)A跳轉(zhuǎn)A的詳情頁(yè),列表頁(yè)A緩存

  • 詳情頁(yè)沒(méi)做任何操作,跳回列表頁(yè)A,列表頁(yè)A不刷新,列表頁(yè)A頁(yè)碼不變
  • 詳情頁(yè)進(jìn)行了編輯操作,跳回列表頁(yè)A,列表頁(yè)A刷新,列表頁(yè)A頁(yè)碼不變
  • 詳情頁(yè)進(jìn)行了新建操作,跳回列表頁(yè)A,列表頁(yè)A刷新,列表頁(yè)A頁(yè)碼變?yōu)?

從列表頁(yè)A跳轉(zhuǎn)列表頁(yè)B,列表頁(yè)A不緩存

總結(jié)就是,一個(gè)頁(yè)面只有跳轉(zhuǎn)指定頁(yè)面的時(shí)候才緩存,并且當(dāng)返回這個(gè)被緩存的頁(yè)面時(shí),可以控制是否刷新。

代碼

1、安裝react-activation

"react-activation": "^0.10.2",

2、給路由增加meta

這個(gè)項(xiàng)目使用的是集中式配置路由,我增加了meta屬性,meta.keepAlive存在表示這是一個(gè)需要被keepAlive的路由,meta.keepAlive.toPath表示只有當(dāng)前往這個(gè)路由的時(shí)候,需要緩存

const routes = [
    ...
    {
        name: '商品管理(商城商品)', 
        path: '/web/supplier/goods/mallgoodsmgr',
        component: './supplier/goods/goodsManage',
        meta: {
          keepAlive: {
            toPath: '/web/supplier/goods/mallgoodsmgr/detail', // 只有去詳情頁(yè)的時(shí)候 才需要緩存 商品管理(商城商品)這個(gè)路由
          },
        },
    }
    ...
]

3、根組件中渲染

在根組件中,用<AliveScope/>包裹整個(gè)應(yīng)用,用<KeepAlive/>包裹需要緩存的頁(yè)面。文檔中這部分寫在<App/>中,如果是umi可以寫在layouts里。
通過(guò)tree的扁平化計(jì)算獲取全部的帶有meta.keepAlive的routes:keepAliveRoutes,通過(guò)location.pathname判斷,如果當(dāng)前頁(yè)面是需要keepAlive的,那么就需要用<KeepAlive/>包裹。

import KeepAlive, { AliveScope, useAliveController } from 'react-activation'

// tree扁平化
function treeToList(tree, childrenKey = 'routes') {
? var queen = []
? var out = []
? queen = queen.concat(tree)
? while (queen.length) {
? ? var first = queen.shift()
? ? if (first[childrenKey]) {
? ? ? queen = queen.concat(first[childrenKey])
? ? ? delete first[childrenKey]
? ? }
? ? out.push(first)
? }
? return out
}

// 從routes路由tree里,拿到所有meta.keepAlive的路由:keepAliveRoutes
const allFlatRoutes = treeToList(routes) // 所有路由
const keepAliveRoutes = allFlatRoutes.filter((item) => item.meta?.keepAlive) // keepAlive的路由

function Index(props) {
? const location = useLocation()
??
? const routeItem = keepAliveRoutes.find(
? ? (item) => item.path == location.pathname
? ) // from 頁(yè)面

? let dom = props.children
? if (routeItem) {
? ? dom = <KeepAlive id={location.pathname}>{props.children}</KeepAlive> // id 一定要加 否則 keepAlive的頁(yè)面 跳轉(zhuǎn) 另一個(gè)keepAlive的頁(yè)面 會(huì)有問(wèn)題
? }

? return (
? ? <AliveScope>
? ? ? <div className={styles.page_container}>{dom}</div>
? ? </AliveScope>
? )
}

注意AliveScope中包含多個(gè)KeepAlive的話,<KeepAlive/>一定要帶id。

4、跳轉(zhuǎn)指定頁(yè)面的時(shí)候才緩存

上一步之后,頁(yè)面雖然被緩存,但是它跳轉(zhuǎn)任何頁(yè)面都會(huì)緩存,我們需要只有跳轉(zhuǎn)指定頁(yè)面的時(shí)候才緩存。
我的方法是

如果跳轉(zhuǎn)的頁(yè)面正好是它自己的meta.keepAlive.toPath,那就不做任何操作(因?yàn)榇藭r(shí)本頁(yè)面已經(jīng)被KeepAlive包裹了,處于緩存的狀態(tài))
如果不是它自己的meta.keepAlive.toPath,調(diào)用clear方法,清空緩存

4.1 clear方法

react-activation提供useAliveController可以手動(dòng)控制緩存,其中clear方法用于清空所有緩存中的 KeepAlive

4.2 用狀態(tài)管理記錄toPath

監(jiān)聽(tīng)history,用狀態(tài)管理(我用的dva)記錄即將前往的頁(yè)面(下一個(gè)頁(yè)面)toPath
我通過(guò)dva記錄應(yīng)用即將前往的頁(yè)面

const GlobalModel = {
? namespace: 'global',

? state: {
? ? /**
? ? ?* keepAlive
? ? ?*/
? ? toPath: '',
? ? keepAliveOptions: {}, // 給keepAlive的頁(yè)面 傳的options
? },

? effects: {},

? reducers: {
? ? save(state, { payload }) {
? ? ? return {
? ? ? ? ...state,
? ? ? ? ...payload,
? ? ? }
? ? },
? ? setToPath(state, { payload }) {
? ? ? return {
? ? ? ? ...state,
? ? ? ? toPath: payload,
? ? ? }
? ? },
? },

? subscriptions: {
? ? setup({ history, dispatch }) {
? ? ? // Subscribe history(url) change, trigger `load` action if pathname is `/`
? ? ? history.listen((route, typeStr) => {
? ? ? ? const { pathname } = route
? ? ? ? dispatch({
? ? ? ? ? type: 'setToPath',
? ? ? ? ? payload: pathname,
? ? ? ? })
? ? ? })
? ? },
? },
}

4.3 給根組件增加useEffect
根組件從dva中讀取即將訪問(wèn)的頁(yè)面toPath,然后加一個(gè)useEffect,如果即將前往的頁(yè)面不是當(dāng)前路由自己的meta.keepAlive.toPath,就執(zhí)行react-activation提供的clear方法

...

function Index(props) {
? const location = useLocation()
? const toPath = props.global.toPath // 從dva中拿到 將要訪問(wèn)的頁(yè)面
??
? const routeItem = keepAliveRoutes.find(
? ? (item) => item.path == location.pathname
? ) // from 頁(yè)面
??
??
? /// 新加代碼
? /// 新加代碼
? /// 新加代碼
? useEffect(() => {
? ? console.log('toPath改變', toPath)

? ? // from頁(yè)面 是需要keepAlive的頁(yè)面
? ? if (routeItem) {
? ? ? console.log('from頁(yè)面 是需要keepAlive的頁(yè)面', routeItem)
? ? ? if (toPath == routeItem.meta?.keepAlive.toPath) {
? ? ? ? // 所去的 頁(yè)面 正好是當(dāng)前這個(gè)路由的 keepAlive.toPath
? ? ? ? console.log('所去的 頁(yè)面 正好是當(dāng)前這個(gè)路由的 keepAlive.toPath,不做什么')
? ? ? } else {
? ? ? ? console.log('clear')
? ? ? ? if (aliveController?.clear) {
? ? ? ? ? aliveController.clear()
? ? ? ? }
? ? ? }
? ? }
? }, [toPath])
? /// 新加代碼 end

? let dom = props.children
? if (routeItem) {
? ? dom = <KeepAlive id={location.pathname}>{props.children}</KeepAlive> // id 一定要加 否則 keepAlive的頁(yè)面 跳轉(zhuǎn) 另一個(gè)keepAlive的頁(yè)面 會(huì)有問(wèn)題
? }

? return (
? ? <AliveScope>
? ? ? <div className={styles.page_container}>{dom}</div>
? ? </AliveScope>
? )
}
export default connect(({ global, login }) => ({ global, login }))(Index)

4.4 優(yōu)化

現(xiàn)在有一個(gè)問(wèn)題:從列表A跳轉(zhuǎn)詳情頁(yè),然后跳轉(zhuǎn)列表B,再跳轉(zhuǎn)列表A的時(shí)候,A是不刷新的:
列表A => 詳情頁(yè) => 列表B => 列表A 此時(shí)列表A不刷新或者空白。
因?yàn)閺脑斍轫?yè)出來(lái)(跳轉(zhuǎn)列表B)的時(shí)候,我們沒(méi)有清空列表A的緩存。
所以要檢查當(dāng)前頁(yè)面是否是某個(gè)需要keepAlive頁(yè)面的toPath頁(yè)面

根組件:

function Index(){
? ...
??
? const parentItem = keepAliveRoutes.find((item) => item.meta?.keepAlive?.toPath == location.pathname) // parentItem存在表示 當(dāng)前頁(yè)面 是某個(gè)keepAlive的頁(yè)面 的toPath

? useEffect(() => {
? ? console.log('toPath改變', toPath)

? ? ...
? ??
? ? /// 新加代碼
? ? /// 新加代碼
? ? /// 新加代碼
? ? // from頁(yè)面 是某個(gè)keepAlive的頁(yè)面 的toPath
? ? if (parentItem) {
? ? ? console.log('from頁(yè)面 是某個(gè)keepAlive的頁(yè)面 的toPath,parentItem', parentItem)
? ? ? if (toPath == parentItem.path) {
? ? ? ? // 所去的 頁(yè)面是 parentItem.path
? ? ? ? console.log('所去的 頁(yè)面是 parentItem.path,不做什么')
? ? ? } else {
? ? ? ? console.log('clear')
? ? ? ? if (aliveController?.clear) {
? ? ? ? ? aliveController.clear()
? ? ? ? }
? ? ? }
? ? }
? }, [toPath])
??
? ...
}

5、抽離邏輯到自定義hooks

useKeepAliveLayout.js

import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import KeepAlive, { AliveScope, useAliveController } from 'react-activation'
import routes from '../../config/router.config'

// tree扁平化
function treeToList(tree, childrenKey = 'routes') {
? var queen = []
? var out = []
? queen = queen.concat(tree)
? while (queen.length) {
? ? var first = queen.shift()
? ? if (first[childrenKey]) {
? ? ? queen = queen.concat(first[childrenKey])
? ? ? delete first[childrenKey]
? ? }
? ? out.push(first)
? }
? return out
}

const allFlatRoutes = treeToList(routes) // 所有路由
const keepAliveRoutes = allFlatRoutes.filter((item) => item.meta?.keepAlive) // keepAlive的路由

function index(props) {
? const location = useLocation()

? // keep alive
? const aliveController = useAliveController()

? const toPath = props.global.toPath // 將要訪問(wèn)的頁(yè)面
? const routeItem = keepAliveRoutes.find((item) => item.path == location.pathname) // from 頁(yè)面
? const parentItem = keepAliveRoutes.find((item) => item.meta?.keepAlive?.toPath == location.pathname)

? useEffect(() => {
? ? console.log('toPath改變', toPath)

? ? // from頁(yè)面 是需要keepAlive的頁(yè)面
? ? if (routeItem) {
? ? ? console.log('from頁(yè)面 是需要keepAlive的頁(yè)面', routeItem)
? ? ? if (toPath == routeItem.meta?.keepAlive.toPath) {
? ? ? ? // 所去的 頁(yè)面 正好是當(dāng)前這個(gè)路由的 keepAlive.toPath
? ? ? ? console.log('所去的 頁(yè)面 正好是當(dāng)前這個(gè)路由的 keepAlive.toPath,不做什么')
? ? ? } else {
? ? ? ? console.log('clear')
? ? ? ? if (aliveController?.clear) {
? ? ? ? ? aliveController.clear()
? ? ? ? }
? ? ? }
? ? }

? ? // from頁(yè)面 是某個(gè)keepAlive的頁(yè)面 的toPath
? ? if (parentItem) {
? ? ? console.log('from頁(yè)面 是某個(gè)keepAlive的頁(yè)面 的toPath,parentItem', parentItem)
? ? ? if (toPath == parentItem.path) {
? ? ? ? // 所去的 頁(yè)面是 parentItem.path
? ? ? ? console.log('所去的 頁(yè)面是 parentItem.path,不做什么')
? ? ? } else {
? ? ? ? console.log('clear')
? ? ? ? if (aliveController?.clear) {
? ? ? ? ? aliveController.clear()
? ? ? ? }
? ? ? }
? ? }
? }, [toPath])

? return {
? ? fromIsNeedKeepAlive: routeItem,
? }
}

export default index

根組件只需要引入這個(gè)hooks就可以了:

function Index(props) {
? const location = useLocation()

? const { fromIsNeedKeepAlive } = useKeepAliveLayout(props) // 關(guān)鍵代碼關(guān)鍵代碼關(guān)鍵代碼

? let dom = props.children
? if (fromIsNeedKeepAlive) {
? ? dom = <KeepAlive id={location.pathname}>{props.children}</KeepAlive> // id 一定要加 否則 keepAlive的頁(yè)面 跳轉(zhuǎn) 另一個(gè)keepAlive的頁(yè)面 會(huì)有問(wèn)題
? }

? return (
? ? <AliveScope>
? ? ? <div className={styles.page_container}>{dom}</div>
? ? </AliveScope>
? )
}

6、 從詳情頁(yè)返回列表頁(yè)的時(shí)候,控制列表頁(yè)是否刷新,即返回傳參

現(xiàn)在只剩下這最后一個(gè)問(wèn)題了,其實(shí)就是keepAlive的頁(yè)面,goBack傳參的問(wèn)題

思路:

  • 狀態(tài)管理中增加一個(gè)keepAliveOptions對(duì)象,這就是詳情頁(yè)給列表頁(yè)傳的參數(shù)
  • 詳情頁(yè)執(zhí)行g(shù)oBack的時(shí)候,調(diào)用狀態(tài)管理dispatch修改keepAliveOptions
  • 列表頁(yè)監(jiān)聽(tīng)keepAliveOptions,如果keepAliveOptions改變就執(zhí)行傳入的方法

useKeepAliveOptions.js

import { useEffect } from 'react'
import { useDispatch, useStore } from 'dva'
import { router } from 'umi'

/**
?* @description keepAlive的頁(yè)面,當(dāng)有參數(shù)傳過(guò)來(lái)的時(shí)候,可以用這個(gè)監(jiān)聽(tīng)到
?* @param {(options:object)=>void} func
?*/
export function useKeepAlivePageShow(func) {
? const dispatch = useDispatch()
? const store = useStore()
? const state = store.getState()
? const options = state.global.keepAliveOptions ?? {}

? useEffect(() => {
? ? func(options) // 執(zhí)行
? ? return () => {
? ? ? console.log('keepAlive頁(yè)面 的緩存 卸載')
? ? ? dispatch({
? ? ? ? type: 'global/save',
? ? ? ? payload: {
? ? ? ? ? keepAliveOptions: {},
? ? ? ? },
? ? ? })
? ? }
? }, [JSON.stringify(options)])
}

/**
?* @description PageA(keepAlive的頁(yè)面)去了 PageB, 當(dāng)從PageB goBack,想要給PageA傳參的時(shí)候,需要使用這個(gè)方法
?* @returns {(params:object)=>void}
?*/
export function useKeepAliveGoback() {
? const dispatch = useDispatch()

? function goBack(parmas = {}) {
? ? dispatch({
? ? ? type: 'global/save',
? ? ? payload: {
? ? ? ? keepAliveOptions: parmas,
? ? ? },
? ? })
? ? router.goBack()
? }

? return goBack
}

使用:

詳情頁(yè)

import { useKeepAliveGoback } from '@/hooks/useKeepAliveOptions'

function Index(){
? ? ...
? ? const keepAliveGoback = useKeepAliveGoback() // 用于給上一頁(yè)keepAlive的頁(yè)面 傳參
? ? ...
? ??
? ? return (
? ? ? ? <>
? ? ? ? ? ? ...
? ? ? ? ? ? <button onClick={() => {
? ? ? ? ? ? ? ? keepAliveGoback({ isAddSuccess: true }) // 給列表頁(yè)傳options
? ? ? ? ? ? }></button>
? ? ? ? ? ? ...
? ? ? ? </>
? ? )
}

列表頁(yè)

import { useKeepAlivePageShow } from '@/hooks/useKeepAliveOptions'

function Index(){
? ? ...
? ? // options: isAddSuccess isEditSuccess
? ? useKeepAlivePageShow((options) => {
? ? ? ? console.log('keepAlive options', options)
? ? ? ? if (options.isAddSuccess) {
? ? ? ? ? // 新建成功 // 列表頁(yè)碼變?yōu)? 并且刷新
? ? ? ? ? search()
? ? ? ? } else if (options.isEditSuccess) {
? ? ? ? ? // 編輯成功 // 列表頁(yè)碼不變 并且刷新
? ? ? ? ? getData()
? ? ? ? }
? ? })
? ??
? ? ...
? ??
? ? return <>...</>
}

相關(guān)文檔

react-activation
dva文檔

到此這篇關(guān)于使用react-activation實(shí)現(xiàn)keepAlive支持返回傳參的文章就介紹到這了,更多相關(guān)react-activation keepAlive返回傳參內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React+valtio響應(yīng)式狀態(tài)管理

    React+valtio響應(yīng)式狀態(tài)管理

    Valtio是一個(gè)很輕量級(jí)的響應(yīng)式狀態(tài)管理庫(kù),使用外部狀態(tài)代理去驅(qū)動(dòng)React視圖來(lái)更新,本文主要介紹了React+valtio響應(yīng)式狀態(tài)管理,感興趣的可以了解一下
    2023-12-12
  • 深入理解React?State?原理

    深入理解React?State?原理

    本文主要介紹了React?State?原理,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • react實(shí)現(xiàn)鼠標(biāo)懸停在SVG地圖上某個(gè)區(qū)域時(shí)上方呈現(xiàn)柱形圖效果

    react實(shí)現(xiàn)鼠標(biāo)懸停在SVG地圖上某個(gè)區(qū)域時(shí)上方呈現(xiàn)柱形圖效果

    這篇文章主要介紹了react實(shí)現(xiàn)鼠標(biāo)懸停在SVG地圖上某個(gè)區(qū)域時(shí),其上方呈現(xiàn)柱形圖,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • React中父組件如何獲取子組件的值或方法

    React中父組件如何獲取子組件的值或方法

    這篇文章主要介紹了React中父組件如何獲取子組件的值或方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • React Fiber與調(diào)和深入分析

    React Fiber與調(diào)和深入分析

    Fiber可以理解為一個(gè)執(zhí)行單元,每次執(zhí)行完一個(gè)執(zhí)行單元,React Fiber就會(huì)檢查還剩多少時(shí)間,如果沒(méi)有時(shí)間則將控制權(quán)讓出去,然后由瀏覽器執(zhí)行渲染操作,這篇文章主要介紹了React Fiber架構(gòu)原理剖析,需要的朋友可以參考下
    2022-11-11
  • 基于React封裝一個(gè)層次模糊效果的容器組件

    基于React封裝一個(gè)層次模糊效果的容器組件

    這篇文章主要為大家詳細(xì)介紹了如何基于React封裝一個(gè)層次模糊效果的容器組件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • 一文詳解React渲染優(yōu)化之useImmer

    一文詳解React渲染優(yōu)化之useImmer

    在React日常開(kāi)發(fā)中,我們常常被重復(fù)渲染或無(wú)意義渲染所折磨,窮盡腦汁,做各種優(yōu)化:memo、useMemo、useCallback、immutable等,本文主要講述immutable的簡(jiǎn)約版Immer,感興趣的同學(xué)可以一起來(lái)學(xué)習(xí)
    2023-05-05
  • React應(yīng)用中避免白屏現(xiàn)象的方法小結(jié)

    React應(yīng)用中避免白屏現(xiàn)象的方法小結(jié)

    在開(kāi)發(fā)React應(yīng)用程序時(shí),我們都曾遇到過(guò)這樣的場(chǎng)景:一個(gè)未被捕獲的異常突然中斷了組件的渲染流程,導(dǎo)致用戶界面呈現(xiàn)出一片空白,也就是俗稱的“白屏”現(xiàn)象,本文將探討如何在React應(yīng)用中有效捕獲并處理這些錯(cuò)誤,避免白屏現(xiàn)象的發(fā)生,需要的朋友可以參考下
    2024-06-06
  • react-redux中connect的裝飾器用法@connect詳解

    react-redux中connect的裝飾器用法@connect詳解

    這篇文章主要介紹了react-redux中connect的裝飾器用法@connect詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 淺談react路由傳參的幾種方式

    淺談react路由傳參的幾種方式

    這篇文章主要介紹了淺談react路由傳參的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評(píng)論

绥阳县| 榆林市| 铁岭县| 南部县| 乌鲁木齐市| 张北县| 新乐市| 剑河县| 怀安县| 高阳县| 莎车县| 平塘县| 辽宁省| 巧家县| 屏东市| 历史| 比如县| 洪洞县| 毕节市| 海南省| 滨州市| 永平县| 含山县| 洱源县| 万盛区| 巩留县| 东源县| 谢通门县| 平潭县| 山丹县| 崇义县| 凤山县| 依安县| 吉安市| 乌苏市| 车致| 丽江市| 宕昌县| 黑水县| 绥化市| 乐平市|