JavaScript前端实现快照的示例代码
作者:小丸子不好吃
snapshot 翻译为快照,用于直观获取页面在某个运行时的状态,本文主要为大家详细介绍 snapshot 工具实现的原理,以及其在项目中的使用,需要的可以参考下
简介
snapshot
翻译为快照,用于直观获取页面在某个运行时的状态,将执行操作前后的快照进行存储,可以轻松实现页面状态的重做、撤销功能。
本文主要介绍 snapshot
工具实现的原理,以及其在项目中的使用。
设计
要实现页面状态的历史记录、重做、撤销,需要支持以下几个属性和方法
属性
- 历史记录:存储历史的页面状态,包含页面初始化的状态 到 上一个页面状态
- 撤销记录:存储重做的每一个操作记录,用于撤销后恢复
- 当前记录:临时存储当前页面状态,主要用于下一次操作后,需要将其存储到历史记录
- 上次插入数据时间:插入时间间隔太小时,需要额外处理
// 历史记录 recordList: string[] = [] // 撤销记录,用于重做 redoList: string[] = [] // 当前记录用 currentRecord 变量暂时存储,当用户修改时,再存放到 recordList currentRecord = '' // 上次插入数据时间 time = 0
方法
存储历史记录 push
当用户操作后,更新历史记录。需要考虑以下几点。
- 当前操作时间距离上次插入时间小于 100 ms 时,则替换当前记录并取消执行添加
- 如果当前记录有值,则说明上一次操作是手动插入,将之前缓存的当前记录推入
recordList
,并且需要清空重做记录 - 将当前状态存储到当前记录
- 设置最大历史记录容量,当超过时,将最先插入的数据删除
push(record: PageData) { const nowTime = Date.now() // 防止添加重复的时间,当添加间隔小于 100ms 时,则替换当前记录并取消执行添加 if (this.time + 100 > nowTime) { try { // 将 json 转成字符串存储 this.currentRecord = JSON.stringify(record) } catch (error) { return false } return false } this.time = nowTime // 判断之前是否已经存在currentRecord记录,有则存储到recordList if (this.currentRecord) { this.recordList.push(this.currentRecord) // 增加记录后则应该清空重做记录 this.redoList.splice(0, this.redoList.length) } // 存储当前记录 this.currentRecord = JSON.stringify(record) // 最多存储 30 条记录,超过则删除之前的记录 if (this.recordList.length > 30) { this.recordList.unshift() } return true }
撤销操作 undo
当用户操作后,依赖 push
时存储的历史记录列表,将页面状态回退到上一次的状态,需要注意以下几点:
- 当历史记录没有时,直接返回
- 从历史记录中取出最后一次存储数据
- 若当前记录存在,需要将其存放到重做记录列表
- 需要清空当前记录,防止重复添加,因为撤销后,也会执行
push
存储历史记录方法
undo() { // 没有记录时,返回 false if (this.recordList.length === 0) { return null } const record = this.recordList.pop() // 将当前记录添加到重做记录里面 if (this.currentRecord) { this.redoList.push(this.currentRecord) } // 丢弃当前记录,防止重复添加 this.currentRecord = '' return JSON.parse(record as string) as PageData }
重做操作 redo
当用户操作后,依赖 redoList
列表,将页面状态回退到撤销前的状态,需要注意以下几点:
- 当重做记录没有时,直接返回
- 从重做记录里取出最后一次存储数据
- 如果当前记录有值,需要将其放到历史记录列表
- 需要清空当前记录,防止重复添加,因为重做后,也会执行
push
存储历史记录方法
redo() { // 没有重做记录时,返回 false if (this.redoList.length === 0) { return null } const record = this.redoList.pop() // 添加到重做记录里面 if (this.currentRecord) { this.recordList.push(this.currentRecord) } // 丢弃当前记录,防止重复添加 this.currentRecord = '' return JSON.parse(record as string) as PageData }
过程演示
假设数据列表为 [1, 2, 3, 4]
,当前属性值分别为:
recordList = [1, 2, 3] redoList = [] currentRecord = 4
1、手动添加 5,则会执行 push
方法,执行后属性值分别为
recordList = [1, 2, 3, 4] redoList = [] currentRecord = 5
2、执行1次撤销,则先会执行 undo
,执行后属性值分别为
recordList = [1, 2, 3] redoList = [5] currentRecord = ''
然后执行 push
,将 4 push
进去,执行后属性值分别为
recordList = [1, 2, 3] redoList = [5] currentRecord = 4
3、执行第2次撤销,则先会执行 undo
,执行后属性值分别为
recordList = [1, 2] redoList = [5, 4] currentRecord = ''
然后执行 push
,将 3 push
进去,执行后属性值分别为
recordList = [1, 2] redoList = [5, 4] currentRecord = 3
4、执行1次重做,则先会执行 redo
,执行后属性值分别为
recordList = [1, 2, 3] redoList = [5] currentRecord = ''
然后执行 push
,将 4 push
进去,执行后属性值分别为
recordList = [1, 2, 3] redoList = [5] currentRecord = 4
5、手动添加 6,则会执行 push
方法,执行后属性值分别为
recordList = [1, 2, 3, 4] redoList = [] currentRecord = 6
完整代码
export default class Snapshot { // 历史记录 recordList: string[] = [] // 撤销记录,用于重做 redoList: string[] = [] // 当前记录用 currentRecord 变量暂时存储,当用户修改时,再存放到 recordList currentRecord = '' // 上次插入数据时间 time = 0 push(record: PageData) { const nowTime = Date.now() // 防止添加重复的时间,当添加间隔小于 100ms 时,则替换当前记录并取消执行添加 if (this.time + 100 > nowTime) { try { // 将 json 转成字符串存储 this.currentRecord = JSON.stringify(record) } catch (error) { return false } return false } this.time = nowTime // 判断之前是否已经存在currentRecord记录,有则存储到recordList if (this.currentRecord) { this.recordList.push(this.currentRecord) // 增加记录后则应该清空重做记录 this.redoList.splice(0, this.redoList.length) } try { // 将 json 转成字符串存储 this.currentRecord = JSON.stringify(record) } catch (error) { return } // 最多存储 30 条记录,超过则删除之前的记录 if (this.recordList.length > 30) { this.recordList.unshift() } return true } undo() { // 没有记录时,返回 false if (this.recordList.length === 0) { return null } const record = this.recordList.pop() // 将当前记录添加到重做记录里面 if (this.currentRecord) { this.redoList.push(this.currentRecord) } // 丢弃当前记录,防止重复添加 this.currentRecord = '' return JSON.parse(record as string) as PageData } redo() { // 没有重做记录时,返回 false if (this.redoList.length === 0) { return null } const record = this.redoList.pop() // 添加到重做记录里面 if (this.currentRecord) { this.recordList.push(this.currentRecord) } // 丢弃当前记录,防止重复添加 this.currentRecord = '' return JSON.parse(record as string) as PageData } }
到此这篇关于JavaScript前端实现快照的示例代码的文章就介绍到这了,更多相关JavaScript快照内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!