简介
问题
在React中使用Redux实现高德地图AMap地图实例的缓存和复用一文中,为了避免多次加载地图影响用户体验,采用了Redux进行实例缓存。然而,在后续开发中发现,由于Redux存储的对象必须序列化,而高德地图的实例是不可序列化的。强行存储导致一些功能无法正常使用,例如设置点击事件。
在网上寻找多种解决方案,发现大多数要求存储项可序列化。
解决方案
后来找到了一个简单而有效的办法:将需要缓存的组件从router中独立出来,直接写在父组件中。通过修改CSS的display属性,根据路由path实现组件的隐藏和显示。这种方法的优势在于,路由跳转时,组件并没有被卸载,而是被隐藏。因此,当用户返回该页面时,无需等待组件重新加载。
同理,开发中当遇到某些组件加载需要较长时间且使用频率较高时,使用这种方法,可以有效减少等待时间,提高用户体验。
原理
CSS提供了多个属性来实现组件的隐藏,如下图所示:
(图片来源:截图——css隐藏元素的六种方法_css hidden-CSDN博客)
通过使用`display: none`属性,可以隐藏元素而不占据空间,实现与使用路由的相似效果。实现步骤
- 修改路由文件使用
<></>代替<HidComponent />
import { type RouteObject } from 'react-router-dom'
import Layout from 'your_path_to/layout.tsx'
import HidComponent from 'your_path_to/HidComponent.tsx'
import OtherComponent from 'your_path_to/OtherComponent.tsx'
const AppRoutes: RouteObject[] = [
{
path: '/',
element: <Layout />,
children: [
{
path: '/HidComponent',
element: <></>
},
{
path: '/OtherComponent',
element: <OtherComponent />
}
]
},
{
path: 'OtherComponent',
element: <OtherComponent />
}
]
export default AppRoutes
- 修改
layout.tsx,将<HidComponent />直接放到组件原本被路由渲染到的位置,在我的项目中就是<Outlet />的上方
import React from 'react'
import { Outlet } from 'react-router-dom'
import HidComponent from 'your_path_to/HidComponent'
const App: React.FC = () => {
// DOM
return (
<Layout>
<Header >
......
</Header>
<Content style={{ height: '100%', width: '100%' }}>
......
// 需要被保留的的组件
<HidComponent />
// 路由占位
<Outlet />
......
</Content>
</Layout>
)
}
export default App
- 新建一个CSS类
.hide
.hide {
display: none;
}
- 修改
<HidComponent />,获取当前url,当路径不符时应用.hide类,隐藏组件
import { useEffect, useMemo } from 'react'
import { useLocation } from 'react-router-dom'
import styles from './styles.module.css'
const HidComponent: React.FC = () => {
// 控制地图隐藏
const url = useLocation()
const hidden = useMemo(() => (url.pathname !== '/home'), [url.pathname])
useEffect(() => {
// 判断是否隐藏地图
if (!hidden) {
//负载较高的初始化操作
init() //需要判断是否已经初始化
}
}, [hidden])
return (
<div className={hidden ? styles.hide : ''} ></div>
)
}
export default HidComponent
效果对比
优化前:
每次回到地图页面都会重新加载地图,由于地图信息依赖网络。因此网速越慢地图加载延迟越久
使用Redux:
报错:Warning A non-serializable value was detected in an action
使用CSS隐藏:
每次回到地图页面地图都是已经加载好的状态