JavaScript前端實(shí)現(xiàn)快照的示例代碼
簡(jiǎn)介
snapshot
翻譯為快照,用于直觀獲取頁(yè)面在某個(gè)運(yùn)行時(shí)的狀態(tài),將執(zhí)行操作前后的快照進(jìn)行存儲(chǔ),可以輕松實(shí)現(xiàn)頁(yè)面狀態(tài)的重做、撤銷功能。
本文主要介紹 snapshot
工具實(shí)現(xiàn)的原理,以及其在項(xiàng)目中的使用。
設(shè)計(jì)
要實(shí)現(xiàn)頁(yè)面狀態(tài)的歷史記錄、重做、撤銷,需要支持以下幾個(gè)屬性和方法
屬性
- 歷史記錄:存儲(chǔ)歷史的頁(yè)面狀態(tài),包含頁(yè)面初始化的狀態(tài) 到 上一個(gè)頁(yè)面狀態(tài)
- 撤銷記錄:存儲(chǔ)重做的每一個(gè)操作記錄,用于撤銷后恢復(fù)
- 當(dāng)前記錄:臨時(shí)存儲(chǔ)當(dāng)前頁(yè)面狀態(tài),主要用于下一次操作后,需要將其存儲(chǔ)到歷史記錄
- 上次插入數(shù)據(jù)時(shí)間:插入時(shí)間間隔太小時(shí),需要額外處理
// 歷史記錄 recordList: string[] = [] ? // 撤銷記錄,用于重做 redoList: string[] = [] ? // 當(dāng)前記錄用 currentRecord 變量暫時(shí)存儲(chǔ),當(dāng)用戶修改時(shí),再存放到 recordList currentRecord = '' ? // 上次插入數(shù)據(jù)時(shí)間 time = 0
方法
存儲(chǔ)歷史記錄 push
當(dāng)用戶操作后,更新歷史記錄。需要考慮以下幾點(diǎn)。
- 當(dāng)前操作時(shí)間距離上次插入時(shí)間小于 100 ms 時(shí),則替換當(dāng)前記錄并取消執(zhí)行添加
- 如果當(dāng)前記錄有值,則說(shuō)明上一次操作是手動(dòng)插入,將之前緩存的當(dāng)前記錄推入
recordList
,并且需要清空重做記錄 - 將當(dāng)前狀態(tài)存儲(chǔ)到當(dāng)前記錄
- 設(shè)置最大歷史記錄容量,當(dāng)超過(guò)時(shí),將最先插入的數(shù)據(jù)刪除
push(record: PageData) { const nowTime = Date.now() // 防止添加重復(fù)的時(shí)間,當(dāng)添加間隔小于 100ms 時(shí),則替換當(dāng)前記錄并取消執(zhí)行添加 if (this.time + 100 > nowTime) { try { // 將 json 轉(zhuǎn)成字符串存儲(chǔ) this.currentRecord = JSON.stringify(record) } catch (error) { return false } ? return false } ? this.time = nowTime ? // 判斷之前是否已經(jīng)存在currentRecord記錄,有則存儲(chǔ)到recordList if (this.currentRecord) { this.recordList.push(this.currentRecord) // 增加記錄后則應(yīng)該清空重做記錄 this.redoList.splice(0, this.redoList.length) } ? // 存儲(chǔ)當(dāng)前記錄 this.currentRecord = JSON.stringify(record) ? // 最多存儲(chǔ) 30 條記錄,超過(guò)則刪除之前的記錄 if (this.recordList.length > 30) { this.recordList.unshift() } return true }
撤銷操作 undo
當(dāng)用戶操作后,依賴 push
時(shí)存儲(chǔ)的歷史記錄列表,將頁(yè)面狀態(tài)回退到上一次的狀態(tài),需要注意以下幾點(diǎn):
- 當(dāng)歷史記錄沒(méi)有時(shí),直接返回
- 從歷史記錄中取出最后一次存儲(chǔ)數(shù)據(jù)
- 若當(dāng)前記錄存在,需要將其存放到重做記錄列表
- 需要清空當(dāng)前記錄,防止重復(fù)添加,因?yàn)槌蜂N后,也會(huì)執(zhí)行
push
存儲(chǔ)歷史記錄方法
undo() { // 沒(méi)有記錄時(shí),返回 false if (this.recordList.length === 0) { return null } ? const record = this.recordList.pop() ? // 將當(dāng)前記錄添加到重做記錄里面 if (this.currentRecord) { this.redoList.push(this.currentRecord) } ? // 丟棄當(dāng)前記錄,防止重復(fù)添加 this.currentRecord = '' return JSON.parse(record as string) as PageData }
重做操作 redo
當(dāng)用戶操作后,依賴 redoList
列表,將頁(yè)面狀態(tài)回退到撤銷前的狀態(tài),需要注意以下幾點(diǎn):
- 當(dāng)重做記錄沒(méi)有時(shí),直接返回
- 從重做記錄里取出最后一次存儲(chǔ)數(shù)據(jù)
- 如果當(dāng)前記錄有值,需要將其放到歷史記錄列表
- 需要清空當(dāng)前記錄,防止重復(fù)添加,因?yàn)橹刈龊?,也?huì)執(zhí)行
push
存儲(chǔ)歷史記錄方法
redo() { // 沒(méi)有重做記錄時(shí),返回 false if (this.redoList.length === 0) { return null } ? const record = this.redoList.pop() // 添加到重做記錄里面 if (this.currentRecord) { this.recordList.push(this.currentRecord) } ? // 丟棄當(dāng)前記錄,防止重復(fù)添加 this.currentRecord = '' return JSON.parse(record as string) as PageData }
過(guò)程演示
假設(shè)數(shù)據(jù)列表為 [1, 2, 3, 4]
,當(dāng)前屬性值分別為:
recordList = [1, 2, 3] redoList = [] currentRecord = 4
1、手動(dòng)添加 5,則會(huì)執(zhí)行 push
方法,執(zhí)行后屬性值分別為
recordList = [1, 2, 3, 4] redoList = [] currentRecord = 5
2、執(zhí)行1次撤銷,則先會(huì)執(zhí)行 undo
,執(zhí)行后屬性值分別為
recordList = [1, 2, 3] redoList = [5] currentRecord = ''
然后執(zhí)行 push
,將 4 push
進(jìn)去,執(zhí)行后屬性值分別為
recordList = [1, 2, 3] redoList = [5] currentRecord = 4
3、執(zhí)行第2次撤銷,則先會(huì)執(zhí)行 undo
,執(zhí)行后屬性值分別為
recordList = [1, 2] redoList = [5, 4] currentRecord = ''
然后執(zhí)行 push
,將 3 push
進(jìn)去,執(zhí)行后屬性值分別為
recordList = [1, 2] redoList = [5, 4] currentRecord = 3
4、執(zhí)行1次重做,則先會(huì)執(zhí)行 redo
,執(zhí)行后屬性值分別為
recordList = [1, 2, 3] redoList = [5] currentRecord = ''
然后執(zhí)行 push
,將 4 push
進(jìn)去,執(zhí)行后屬性值分別為
recordList = [1, 2, 3] redoList = [5] currentRecord = 4
5、手動(dòng)添加 6,則會(huì)執(zhí)行 push
方法,執(zhí)行后屬性值分別為
recordList = [1, 2, 3, 4] redoList = [] currentRecord = 6
完整代碼
export default class Snapshot { // 歷史記錄 recordList: string[] = [] ? // 撤銷記錄,用于重做 redoList: string[] = [] ? // 當(dāng)前記錄用 currentRecord 變量暫時(shí)存儲(chǔ),當(dāng)用戶修改時(shí),再存放到 recordList currentRecord = '' ? // 上次插入數(shù)據(jù)時(shí)間 time = 0 ? push(record: PageData) { const nowTime = Date.now() // 防止添加重復(fù)的時(shí)間,當(dāng)添加間隔小于 100ms 時(shí),則替換當(dāng)前記錄并取消執(zhí)行添加 if (this.time + 100 > nowTime) { try { // 將 json 轉(zhuǎn)成字符串存儲(chǔ) this.currentRecord = JSON.stringify(record) } catch (error) { return false } ? return false } ? this.time = nowTime ? // 判斷之前是否已經(jīng)存在currentRecord記錄,有則存儲(chǔ)到recordList if (this.currentRecord) { this.recordList.push(this.currentRecord) // 增加記錄后則應(yīng)該清空重做記錄 this.redoList.splice(0, this.redoList.length) } ? try { // 將 json 轉(zhuǎn)成字符串存儲(chǔ) this.currentRecord = JSON.stringify(record) } catch (error) { return } ? // 最多存儲(chǔ) 30 條記錄,超過(guò)則刪除之前的記錄 if (this.recordList.length > 30) { this.recordList.unshift() } return true } ? undo() { // 沒(méi)有記錄時(shí),返回 false if (this.recordList.length === 0) { return null } ? const record = this.recordList.pop() ? // 將當(dāng)前記錄添加到重做記錄里面 if (this.currentRecord) { this.redoList.push(this.currentRecord) } ? // 丟棄當(dāng)前記錄,防止重復(fù)添加 this.currentRecord = '' return JSON.parse(record as string) as PageData } ? redo() { // 沒(méi)有重做記錄時(shí),返回 false if (this.redoList.length === 0) { return null } ? const record = this.redoList.pop() // 添加到重做記錄里面 if (this.currentRecord) { this.recordList.push(this.currentRecord) } ? // 丟棄當(dāng)前記錄,防止重復(fù)添加 this.currentRecord = '' return JSON.parse(record as string) as PageData } }
到此這篇關(guān)于JavaScript前端實(shí)現(xiàn)快照的示例代碼的文章就介紹到這了,更多相關(guān)JavaScript快照內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript實(shí)現(xiàn)倒計(jì)時(shí)(防頁(yè)面刷新)實(shí)例
本文分享了Javascript實(shí)現(xiàn)倒計(jì)時(shí)并且頁(yè)面不刷新的實(shí)例,具有很好的參考價(jià)值,需要的朋友一起來(lái)看下吧2016-12-12javascript中Date對(duì)象的使用總結(jié)
本文介紹了Date對(duì)象的使用方法,清晰明了,實(shí)現(xiàn)方法有多種,僅供大家參考,希望對(duì)大家有所幫助,下面就跟小編一起來(lái)看看吧2016-11-11微信企業(yè)號(hào)開(kāi)發(fā)之微信考勤百度地圖定位
本文給大家介紹微信企業(yè)號(hào)開(kāi)發(fā)之微信考勤百度地圖定位,有需要的朋友參考下本篇文章2015-09-09ionic2 tabs 圖標(biāo)自定義實(shí)例
這篇文章主要介紹了ionic2 tabs 圖標(biāo)自定義,需要的朋友可以參考下2017-03-03