【前端页面缓存技术方案】

article/2025/3/15 6:14:46

前端页面缓存技术方案

  • 关于页面缓存数据的纯前端技术方案
    • 背景
    • 项目存在的现有方案
    • 思考🤔
    • 其他技术调研
      • react-activation
      • react-router-cache-route
    • 结论

关于页面缓存数据的纯前端技术方案

背景

为了优化用户的体验,可能会遇到这样的需求:在列表页跳到详情页然后又返回列表的时候,需要保持状态和滚动位置;或是页面内切换组件(比如切换 Tab )的时候,需要保持状态。但目前由于react router只保留当前匹配第一个的路由状态,卸载掉其他路由。切换页面或Tab时会销毁上个组件,所以现状是每次返回时都是当前页面的初始状态。

项目存在的现有方案

思路:将列表页的数据全部保存起来,再次返回列表页的时候,进行读取数据

  • 本地存储
    通过localStorage或者sessionStorage缓存列表页的状态,当再次返回列表页时,通过获取本地缓存数据来实现保留当前页面的状态。
    弊端:

    • 如果用户手动清除了本地缓存后,再次返回到列表页,将获取不到保存的数据;
    • 如果当前分页为2,返回列表页后再增加条件搜索,搜索结果数据不足达到2页,可能会有报错问题
  • redux存储
    对于react实现的SPA页面,我们可以通过创建store存储列表数据保留在一级页面路径下,然后再次返回列表页面后,通过react-redux的connect方法将state中的数据绑定到页面的props中,方便访问。
    弊端:

    • 列表数据较多时,需要存储多个数据状态,不易维护;
    • 在页面路径较深或子路径多时,其他页面也会访问到store中的数据,导致数据较多,出现冗余
  • url携带参数存储
    将列表页的数据状态作为参数保存在页面的url中,页面参数通过列表页面数据变化而实时改变。当详情页再次返回到列表页,通过解析url参数来展示页面相应状态。
    弊端:

    • 随着切换筛选条件次数增多,浏览器会记录每一次的url变化,当用户点击浏览器回退或前进按钮时,浏览器会从历史记录中获取返回url,用户多次点击返回,可能导致页面展示上一次筛选状态,而并非跳转页面,影响用户体验
    • 如果列表页的数据状态较多,url上的公共业务参数也较多,由于url参数长度有限,可能会出现丢失参数的问题
  • react context
    和redux相似,将列表页面数据保存到 context 中,context provider 放置在列表页和详情页共同的父组容器上。弊端也是会存在不易维护的问题,还有在子组件中更新 context 容易引发死循环的问题。(项目没有使用context,因此放弃)

思考🤔

除了以上存储页面各个数据的方式以外,是否还有其他方式解决呢?

联想到了在手机屏幕上进行操作App的页面切换,我们可以理解是在当前屏幕上做一层层叠加,用户看到的一直都是最上层,当用户返回页面,即看到下一层页面,每一层的页面数据都有所保留,因此在切换页面的时候并没有销毁,而是叠加。

通过移动端的实现,联想PC端是不是也可以不让当前页面销毁?达到一个伪销毁的状态,将页面保存到另一个容器里,然后当访问到该路由时,直接把容器里的数据取出再赋给真实的DOM组件中。

其他技术调研

react-activation

git地址:https://github.com/CJY0208/react-activation

import React, { Component, createContext } from 'react'const { Provider, Consumer } = createContext()
const withScope = WrappedComponent => props => (<Consumer>{keep => <WrappedComponent {...props} keep={keep} />}</Consumer>
)export class AliveScope extends Component {nodes = {}state = {}keep = (id, children) =>new Promise(resolve =>this.setState({[id]: { id, children }},() => resolve(this.nodes[id])))render() {return (<Provider value={this.keep}>{this.props.children}{Object.values(this.state).map(({ id, children }) => (<divkey={id}ref={node => {this.nodes[id] = node}}>{children}</div>))}</Provider>)}
}@withScope
class KeepAlive extends Component {constructor(props) {super(props)this.init(props)}init = async ({ id, children, keep }) => {const realContent = await keep(id, children)this.placeholder.appendChild(realContent)}render() {return (<divref={node => {this.placeholder = node}}/>)}
}export default KeepAlive

实现大致过程是将AliveScope组件通过上下文,把一个keep方法传递下去,将KeepAlive组件包裹需要缓存的组件,然后一个高阶组件获取到 keep 方法,并把 children 属性传入 KeepAlive 组件,在 KeepAlive 组件中调用 keep 方法,把 children 属性缓存到 AliveScope 的 state 中。在 state 更新后,把 ref (真实 DOM)返回给 KeepAlive 组件。KeepAlive 组件拿到真实 DOM 后,把它移动到自己组件内的某个占位中。
在这里插入图片描述主要思路:把 children 包裹起来并且传递出去,在缓存组件内被渲染,当前组件正常地更新卸载。当前组件卸载的时候,children 也被卸载了,但是它的虚拟 DOM 已经被缓存在了缓存组件中。这个组件重新被加载的时候,把缓存直接渲染后移入当前组件,就恢复了组件卸载前状态。

示例

import React from 'react';
import ReactDOM from 'react-dom';
import { AliveScope, KeepAlive } from 'react-activation'
import Test from './views/Test';ReactDOM.render(<AliveScope><KeepAlive name="Test"><Test /></KeepAlive></AliveScope>,document.getElementById('root'),
);

弊端:

  • 适用场景不灵活,例如当用户只在点击浏览器回退按钮时读取缓存,其他场景返回不缓存时,该方案实现起来较难,因此在特定场景下缓存页面,不推荐使用

react-router-cache-route

git地址:https://github.com/CJY0208/react-router-cache-route
通过“重写“Switch、Route两个组件,控制页面组件的生命周期,使其在不匹配的时候,记录滚动位置并从dom上移除,在匹配的时候,重新挂载到dom上并恢复滚动位置,整个过程组件实例并未销毁,从而达到缓存实例数据状态的目的。

示例:

<AppContainer><CustomHeader /><CacheSwitch>{routes.map((route: RouteType, index:number) => {return route.cache ? (<CacheRouteexact={true}path={`/${route.routerPath}`}key={index}component={route.component}/>) : (<Route exact={true}path={`/${route.routerPath}`}key={index}component={route.component}/>)})}<Redirect to='/login' /></ CacheSwitch>
</AppContainer>

CacheRoute
给组件套上Route、CacheComponent等wrapper,配合computedMatchForCacheRoute欺骗Route组件,从而确保其Route内嵌套的CacheComponent会一直渲染。通过可传props参数项,可以在指定场景进行缓存,适用场景更加灵活 。
在这里插入图片描述
弊端:

  • 项目框架受限,当项目采用umi等一些对router组件进行封装的框架时,项目对router组件改装起来较难,因此不适合该方案

结论

  • 通过将页面数据进行保存数据,更容易让人理解,但是每次页面有此需求都需要再次开发需要存储的数据,开发成本比较大,不易维护;
  • 通过第三方插件将页面组件保存另一个容器里,开发成本低,但会因项目框架的设计,使用可能会受限制;

http://chatgpt.dhexx.cn/article/63mWMd9U.shtml

相关文章

前端常用缓存技术

http://www.cnblogs.com/belove8013/p/8134067.html 今天刚上班就听到群里的几位大佬在讨论所开发的系统需要重复的登录的恶心之处&#xff0c;听各位大佬争辩的同时&#xff0c;想到了自己以前整理过的缓存技术&#xff0c;算是比较全面的&#xff0c;当然了只是帮助自己理解的…

我的网站心得之缓存技术(前端篇)

在前端面试中&#xff0c;storage是面试官经常问的问题&#xff0c;我先问你几个问题&#xff0c;如果你回答不上来&#xff0c;那么你应该阅读一下&#xff1a;知道storage吗&#xff1f;storage存储的数据类型有什么&#xff1f;sessionStorage的生命周期&#xff1f;你都用l…

中高级前端工程师都需要熟悉的技能--前端缓存

前言 web缓存是高级前端工程师必修技能。是我们变成大牛过程中绕不开的知识点。 文章会尽量用通俗易懂的言语来细说web缓存的概念和用处。 本期文章的大纲是 什么是web缓存&#xff08;前端缓存&#xff09; 缓存可以解决什么问题&#xff1f;他的缺点是什么&#xff1f; …

ovo svm_反思我在OVO担任远程产品设计实习生的时间

ovo svm In a quiet bedroom accompanied only by the low humming of my laptop fan, I sat before a Google Hangouts meeting, and got to know my colleagues for the first time, unaware of the joy of a ride that was waiting for me at OVO Design. 在一个安静的卧室里…

反思最近这些时日的荒废

为什么80%的码农都做不了架构师&#xff1f;>>> 算是一时兴起&#xff0c;最近lol排位已经将自己的折磨的不成人样。闲了这么久&#xff0c;是时候找份工作了。最近一直没敢跟家里人打电话&#xff0c;实在不知道该说些什么&#xff0c;一开口便是谎言。是否自己真的…

团队愿景_周一的愿景,每日的成果,周五的远程团队管理反思

团队愿景 My friend J.D. Meier has an amazing blog called Sources of Insight and hes written a fantastic book called Getting Results the Agile Way. You can buy his book on Amazon (its free on Kindle Unlimited!). I put J.D. up there with David Allen and Step…

WPBeginner年满10岁-反思,更新和WordPress赠品(奖金124,000美元以上)

Wow, it’s the tenth fourth. Today, WPBeginner is officially 10 years old — feels unreal to type this! 哇&#xff0c;是第十位 今天&#xff0c;WPBeginner正式成立了10岁-键入此图标感到不切实际&#xff01; Like every year, I want to take a few minutes and d…

误泄露公司代码、疫情期间被裁,一个“菜鸟”程序员的生存日记

作者 | Adam Hughes 译者 | Sambodhi 策划 | Tina 编辑&#xff5c;燕珊 “我是如何从每一次失败中成长起来的。” 身为程序员&#xff0c;我们往往都了解大神级程序员的故事。比如很小就开始编程&#xff0c;在 11 岁时就创建了第一家能盈利的网站&#xff0c;16 岁上大学、17…

失败需要反思

2019独角兽企业重金招聘Python工程师标准>>> 公司的第一款游戏是抄袭的COC&#xff0c;然而我加入进去的时候开发已过半&#xff0c;进入之后主要是参与一些新的系统与玩法的开发&#xff0c;在我加入到这个项目之后还开发了大概半年时间&#xff0c;据说此前已经开…

CTF笔记 个人HNCTF反思(部分题目)

文章目录 [WEEK2]easy_include自己的胡思乱想WP [WEEK2]easy_unserexp [WEEK2]easy_sqlWP [WEEK2]ez_SSTIPAYLOAD [WEEK4]pop子和pipi美总结 怎么说呢&#xff0c;这次充分感觉到了自己的无能&#xff0c;可能因为在比赛马上结束的时候加入&#xff0c;让我没心思慢慢思考&…

一名大学毕业生的反思_反思我大学毕业时的软件工程师的第一年

一名大学毕业生的反思 Note: This post is mainly targeted towards students who are about to graduate or have already graduated and are preparing to start their new full-time job. Some of the examples used are specific to my experience as a New Grad Software …

华清远见嵌入式培训_第二周回顾与反思

目录 前言 周一 一、switch..case 1.1 注意事项 1.2 使用练习 二、循环控制语句 2.1 使用goto实现循环 2.2 while循环 2.3 do..while 循环 2.4 for 循环 2.5 死循环 2.6 辅助控制关键字 周二 一、数组 1.1 一维数组 1.2 数组越界问题 1.3 二维数组 1.4 编码练…

让计算机开口说话教学反思,英语教学反思(合集15篇)

英语教学反思(合集15篇) 身为一位优秀的老师&#xff0c;课堂教学是我们的工作之一&#xff0c;借助教学反思我们可以快速提升自己的教学能力&#xff0c;我们该怎么去写教学反思呢&#xff1f;以下是小编为大家收集的英语教学反思&#xff0c;希望能够帮助到大家。 英语教学反…

华清远见嵌入式培训_第五周回顾与反思

前言 这是在华清学习的第五个周末&#xff0c;这一周主要学习的是数据结构。老师说数据结构是一门非常庞大的学科&#xff0c;单单是数据结构里的一个小分支&#xff0c;单拎出来一周都未必可以学透&#xff0c;因此这周的数据结构课程里更多的是思维方向的学习&#xff0c;学习…

利用Python识别txt文本并根据其内容进行文件分类

事情是这样的&#xff0c;有一个图片数据集需要根据分成很多类以便于给其设置标签&#xff0c;但所有的图片都在一个文件里&#xff0c;另外又给了个.txt文件&#xff0c;其中每行都是对应图片的类别。例如第1行对应的第0001.jpg是第14类&#xff08;每个类都有多张图片&#x…

C# 批量修改文件名称

目的 对文件夹中所有文件名实现批量修改&#xff08;添加新字符&#xff09; 思路 获取文件夹路径获取文件夹中所有文件的文件名对文件名进行批量修改 方法 窗口设计 获取文件夹路径 使用FolderBrowserDialog控件获取文件夹路径&#xff0c;并用Directory.Exists方法对路径…

Unity Shader入门精要之Unity 提供的内置文件和变量

Unity系列文章目录 文章目录 Unity系列文章目录前言5.3.1 内置的包含文件5.3.2 内置的变量 二、Unity 提供的Cg/HLSL 语义5.5 程序员的烦恼&#xff1a;Debug5.6 小心&#xff1a;渲染平台的差异5.7 Shader 整洁之道参考 前言 上一节讲述了如何在Unity 中编写一个基本的顶点/片…

《python数学实验与建模》(10)图论模型

10.1 写出图10.20所示非赋权无向图的关联矩阵和邻接矩阵 绘制图 import networkx as nx import pylab as plt import numpy as np Anp.zeros((6,6)) List[(1,2),(1,4),(2,3),(3,4),(3,5),(3,6),(4,5),(4,6),(5,6)] for i in List:A[i[0]-1,i[1]-1]1 Gnx.Graph(A) posnx.spring…

2021年美国数学建模C题的数据处理

2021年美国数学建模C题的数据处理 C题数据分类存放部分批量提取图像数据转化jpg图像格式 C题数据分类存放部分 在拿到C题的数据后&#xff0c;避让要做的一个事情是图像数据的分类。根据2021MCM_ProblemC_ Images_by_GlobalID表格中&#xff0c;可以将图片和ID号对应起来&…

Unity Shader入门精要笔记(五):其他数学相关介绍

本系列文章由Aimar_Johnny编写&#xff0c;欢迎转载&#xff0c;转载请标明出处&#xff0c;谢谢。 http://blog.csdn.net/lzhq1982/article/details/73747162 前两篇介绍了Unity Shader的主要数学部分&#xff0c;书上还有些相关的数学介绍&#xff0c;将在这篇做最后的总结。…