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

react-router-dom v6版本實(shí)現(xiàn)Tabs路由緩存切換功能

 更新時(shí)間:2023年10月19日 15:51:08   作者:很甜的西瓜  
今天有人問我怎么實(shí)現(xiàn)React-Router-dom類似標(biāo)簽頁緩存,很久以前用的是react-router v5那個(gè)比較容易實(shí)現(xiàn),v6變化挺大,但了解react的機(jī)制和react-router的機(jī)制就容易了,本文介紹react-router-dom v6版本實(shí)現(xiàn)Tabs路由緩存切換,感興趣的朋友一起看看吧

概要

擺了半年攤,好久沒寫代碼了,今天有人問我怎么實(shí)現(xiàn)React-Router-dom類似標(biāo)簽頁緩存。后面看了一下router的官網(wǎng)。很久以前用的是react-router v5那個(gè)比較容易實(shí)現(xiàn)。v6變化挺大,但了解react的機(jī)制和react-router的機(jī)制就容易了.

想做到切換標(biāo)簽保留頁面的內(nèi)容不變,就要了解react的機(jī)制

首先虛擬DOM的機(jī)制就是對比,如果找不到就會重新掛載,找到了就更新。

React-Router的機(jī)制就是匹配路徑,找到了就返回對應(yīng)的路由組件,找不到返回為null

思路就是v6版本提供了Outlet這個(gè)輸出子路元素的組件

一般我們會這樣寫:

但如果要實(shí)現(xiàn)標(biāo)簽的話,就不能這樣寫。但是切換路由,地址一變它就替換了原來的了。所以要做的就是保留所有打開的標(biāo)簽的子路由元素:

主要目的就是保留所有的元素,隱藏路由就行,這樣react diff時(shí),還是會找到對應(yīng)key的路由,這樣它只是會更新路由的組件,而不會重新掛載。

如這樣寫:

效果

完整代碼

新建一個(gè)html復(fù)制進(jìn)去就可以運(yùn)行了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React-router-dom tabs</title>
    <script src="https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
    <link rel="stylesheet"  rel="external nofollow" >
    <script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/antd@5.10.1/dist/antd.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@ant-design/pro-components@2.6.30/dist/pro-components.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@remix-run/router@1.10.0/dist/router.umd.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-router@6.17.0/dist/umd/react-router.production.min.js"></script>
    <script
        src="https://cdn.jsdelivr.net/npm/react-router-dom@6.17.0/dist/umd/react-router-dom.production.min.js"></script>
</head>
<body>
    <div id="app"></div>
    <script type="text/babel" data-preset="env,react">
        const { useCallback, useMemo, useEffect, useRef, useState } = React
        const { ProLayout } = ProComponents
        const { createHashRouter, useOutlet, Navigate, RouterProvider, useLocation, Link, useNavigate } = ReactRouterDOM
        const { Tabs, Button, Space, Row, Col, Input, } = antd
        const Home = () => {
            return <div>Home <Input></Input></div>
        }
        const DemoA = () => {
            return <div>DemoA <Input></Input></div>
        }
        const DemoB = () => {
            return <div>DemoB <Input></Input></div>
        }
        const ViewPage = (props) => {
            const outlet = useOutlet()
            return props.render(outlet)
        }
        const BasicLayout = () => {
            const nav = useNavigate()
            const location = useLocation()
            const route = routes[0]
            const [menuDataMap] = useState(() => new Map())
            const cacheOutletElements = useRef({}).current
            const [tabActiveKey, setTabActiveKey] = useState('')
            const [tabItems, setTabItems] = React.useState([])
            const addTab = useCallback((item) => {
                const existItem = tabItems.find(it => it.key === item.key)
                if (!existItem) {
                    setTabItems([...tabItems, {
                        key: item.key,
                        path: item.path,
                        label: item.name
                    }])
                }
                setTabActiveKey(item.key)
            }, [tabItems])
            const handleSelectMenu = useCallback((selectedKeys) => {
                console.log('handleSelectMenu', selectedKeys)
                let menuKey = selectedKeys[selectedKeys.length - 1]
                let item = menuDataMap.get(menuKey)
                if (item && item.path) {
                    addTab(item)
                }
            }, [addTab])
            const handleTabChange = useCallback((activeKey) => {
                setTabActiveKey(activeKey)
                const item = tabItems.find(d => d.key === activeKey)
                nav(item.path)
            }, [tabItems, nav])
            const handleTabEditChange = useCallback((activeKey, action) => {
                if (action === 'remove') {
                    delete cacheOutletElements[activeKey]
                    const newItems = tabItems.filter(d => d.key !== activeKey)
                    setTabItems(newItems)
                    if (newItems.length) {
                        handleTabChange(newItems[0].key)
                    }
                }
            }, [tabItems, handleTabChange])
            const renderView = useCallback((routeElement) => {
                if (!cacheOutletElements[tabActiveKey]) {
                    cacheOutletElements[tabActiveKey] = <div>{routeElement}</div>
                }
                return Object.keys(cacheOutletElements).map(key => {
                    const element = cacheOutletElements[key]
                    if (key === tabActiveKey) {
                        return React.cloneElement(element, {
                            key: key,
                            style: {
                                display: 'block'
                            }
                        })
                    } else {
                        return React.cloneElement(element, {
                            key: key,
                            style: {
                                display: 'none'
                            }
                        })
                    }
                })
            }, [cacheOutletElements, tabActiveKey])
            return <ProLayout route={route} onSelect={handleSelectMenu} location={location} menuItemRender={(item, defaultDom, menuProps) => {
                if (item.children) {
                    return defaultDom
                }
                menuDataMap.set(item.path, item)
                return <Link to={item.path}>{defaultDom}</Link>
            }}>
                <Tabs hideAdd type='editable-card' onEdit={handleTabEditChange} activeKey={tabActiveKey} onChange={handleTabChange} items={tabItems}>
                </Tabs>
                <ViewPage render={renderView}></ViewPage>
            </ProLayout>
        }
        const routes = [{
            path: '/',
            element: <BasicLayout></BasicLayout>,
            children: [
                {
                    index: true,
                    element: <Navigate to="/home"></Navigate>
                }, {
                    path: 'home',
                    name: "Home",
                    element: <Home></Home>
                }
                , {
                    path: 'a',
                    name: "DemoA",
                    element: <DemoA></DemoA>
                }
                , {
                    path: 'b',
                    name: "DemoB",
                    element: <DemoB></DemoB>
                }
            ]
        }]
        const router = createHashRouter(routes, {
        })
        const App = () => {
            return <RouterProvider router={router}></RouterProvider>
        }
        ReactDOM.createRoot(document.getElementById('app')).render(<App></App>)
    </script>
</body>
</html>

到此這篇關(guān)于react-router-dom v6版本實(shí)現(xiàn)Tabs路由緩存切換的文章就介紹到這了,更多相關(guān)react-router-dom路由緩存切換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React+TS+IntersectionObserver實(shí)現(xiàn)視頻懶加載和自動播放功能

    React+TS+IntersectionObserver實(shí)現(xiàn)視頻懶加載和自動播放功能

    通過本文的介紹,我們學(xué)習(xí)了如何使用 React + TypeScript 和 IntersectionObserver API 來實(shí)現(xiàn)一個(gè)視頻播放控制組件,該組件具有懶加載功能,只有在用戶滾動頁面且視頻進(jìn)入視口時(shí)才開始下載視頻資源,需要的朋友可以參考下
    2023-04-04
  • react項(xiàng)目打包后點(diǎn)擊index.html頁面出現(xiàn)空白的問題

    react項(xiàng)目打包后點(diǎn)擊index.html頁面出現(xiàn)空白的問題

    這篇文章主要介紹了react項(xiàng)目打包后點(diǎn)擊index.html頁面出現(xiàn)空白的問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • React中上傳圖片到七牛的示例代碼

    React中上傳圖片到七牛的示例代碼

    本篇文章主要介紹了React中上傳圖片到七牛的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • React使用ref進(jìn)行訪問DOM元素或組件

    React使用ref進(jìn)行訪問DOM元素或組件

    在 React 里,ref 就像是一個(gè)神奇的小助手,能讓你直接去訪問 DOM 元素或者組件實(shí)例,下面就跟隨小編一起來學(xué)習(xí)一下具體的使用方法吧
    2025-03-03
  • 詳解在React-Native中持久化redux數(shù)據(jù)

    詳解在React-Native中持久化redux數(shù)據(jù)

    這篇文章主要介紹了在React-Native中持久化redux數(shù)據(jù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • react quill中圖片上傳由默認(rèn)轉(zhuǎn)成base64改成上傳到服務(wù)器的方法

    react quill中圖片上傳由默認(rèn)轉(zhuǎn)成base64改成上傳到服務(wù)器的方法

    這篇文章主要介紹了react quill中圖片上傳由默認(rèn)轉(zhuǎn)成base64改成上傳到服務(wù)器的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • React鼠標(biāo)多選功能的配置方法

    React鼠標(biāo)多選功能的配置方法

    本文給大家分享React鼠標(biāo)多選功能,通過導(dǎo)入組件直接包裹已經(jīng)設(shè)計(jì)好的列表即可,操作簡單方便,對React鼠標(biāo)多選相關(guān)知識感興趣的朋友一起看看吧
    2021-05-05
  • react使用antd表單賦值,用于修改彈框的操作

    react使用antd表單賦值,用于修改彈框的操作

    這篇文章主要介紹了react使用antd表單賦值,用于修改彈框的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Remix如何支持原生?CSS方法詳解

    Remix如何支持原生?CSS方法詳解

    這篇文章主要為大家介紹了Remix如何支持原生CSS的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 淺談react性能優(yōu)化的方法

    淺談react性能優(yōu)化的方法

    這篇文章主要介紹了淺談react性能優(yōu)化的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09

最新評論

中西区| 衡南县| 合作市| 军事| 高雄县| 多伦县| 施甸县| 景德镇市| 伊通| 商丘市| 清苑县| 桓台县| 贵德县| 高碑店市| 永顺县| 偏关县| 慈利县| 时尚| 青浦区| 松江区| 堆龙德庆县| 禹城市| 分宜县| 沙湾县| 安西县| 论坛| 庄浪县| 南昌县| 依安县| 肃南| 阿坝县| 呼玛县| 仁布县| 邵阳市| 云林县| 巴林左旗| 民权县| 丘北县| 绵阳市| 通州市| 洛隆县|