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