I Love ReactJS

Implementation scheme of front-end snapshot

introduction

snapshot is translated as a snapshot, which is used to directly obtain the status of the page at a certain runtime. The snapshot before and after the operation is stored, so that the page state can be redone and undone easily.

this article mainly introduces the principle of snapshot tool implementation and its use in the project.

Design

to implement the history, redo and undo of page state, you need to support the following properties and methods

Properties

 // History
 recordList: string[] = []
 ​
 // cancel the record, which is used to redo
 redoList: string[] = []
 ​
 // the current record is temporarily stored in the currentRecord variable, and then stored in recordList when the user modifies it.
 currentRecord = ''
 ​
 // time when the data was last inserted
 time = 0

method

Storage history push

when the user acts, the history is updated. The following points need to be considered.

 push(record: PageData) {
   const nowTime = Date.now()
   // prevent adding repetitive time. When the adding interval is less than 100ms, replace the current record and cancel the add.
   if (this.time + 100 > nowTime) {
     try {
       // convert json to string storage
       this.currentRecord = JSON.stringify(record)
     } catch (error) {
       return false
     }
 ​
     return false
   }
 ​
   this.time = nowTime
 ​
   // determine whether the currentRecord record already exists, and store it in recordList.
   if (this.currentRecord) {
     this.recordList.push(this.currentRecord)
     // after adding records, the redo records should be emptied.
     this.redoList.splice(0, this.redoList.length)
   }
 ​
   // Save the current record
   this.currentRecord = JSON.stringify(record)
 ​
   // store a maximum of 30 records. If more than that, delete the previous records.
   if (this.recordList.length > 30) {
     this.recordList.unshift()
   }
   return true
 }

undo operation undo

when the user relies on the history list stored in push after the user's operation, and returns the page state to the previous state, you should pay attention to the following points:

 undo() {
   // if there is no record, return false
   if (this.recordList.length === 0) {
     return null
   }
 ​
   const record = this.recordList.pop()
 ​
   // add the current record to the redo record
   if (this.currentRecord) {
     this.redoList.push(this.currentRecord)
   }
 ​
   // discard the current record to prevent repeated additions
   this.currentRecord = ''
   return JSON.parse(record as string) as PageData
 }

redo redo

when a user acts, relies on the redoList list to return the page state to the state before undo, you should pay attention to the following points:

 redo() {
   //return false if there is no redo record
   if (this.redoList.length === 0) {
     return null
   }
 ​
   const record = this.redoList.pop()
   // add to the redo record
   if (this.currentRecord) {
     this.recordList.push(this.currentRecord)
   }
 ​
   // discard the current record to prevent repeated additions
   this.currentRecord = ''
   return JSON.parse(record as string) as PageData
 }

process demonstration

suppose the data list is [1, 2, 3, 4] , and the current attribute values are:

 recordList = [1, 2, 3]
 redoList = []
 currentRecord = 4

1, add 5 manually, the push method will be executed, and the attribute value will be

after execution.

 recordList = [1, 2, 3, 4]
 redoList = []
 currentRecord = 5

2. Perform undo once,then undo willbe executed first, and the attribute values after execution are respectively

 recordList = [1, 2, 3]
 redoList = [5]
 currentRecord = ''

Then executepush, put 4push in, and the attribute values after execution are respectively

 recordList = [1, 2, 3]
 redoList = [5]
 currentRecord = 4

3. If the second undo is executed, undo will be executed first, and the attribute value will be

after execution.

 recordList = [1, 2]
 redoList = [5, 4]
 currentRecord = ''

then execute push , insert 3 push , and the attribute value is

after execution.

 recordList = [1, 2]
 redoList = [5, 4]
 currentRecord = 3

4. If a redo is performed once, redo will be executed first, and the attribute value will be

after execution.

 recordList = [1, 2, 3]
 redoList = [5]
 currentRecord = ''

then execute push , enter 4 push , and the attribute value is

after execution.

 recordList = [1, 2, 3]
 redoList = [5]
 currentRecord = 4

5. Manually add 6,the push method will be executed, and the attribute values after execution are respectively

 recordList = [1, 2, 3, 4]
 redoList = []
 currentRecord = 6

complete code

 export default class Snapshot {
     //History
     recordList: string[] = []
 ​
     // cancel the record, which is used to redo
     redoList: string[] = []
 ​
     //The current record is temporarily stored in the currentRecord variable. When the user modifies it, it is stored in recordList.
     currentRecord = ''
 ​
     // time when the data was last inserted
     time = 0
 ​
     push(record: PageData) {
         const nowTime = Date.now()
         // prevent adding repetitive time. When the adding interval is less than 100ms, replace the current record and cancel the add.
         if (this.time + 100 > nowTime) {
             try {
                 // convert json to string storage
                 this.currentRecord = JSON.stringify(record)
             } catch (error) {
                 return false
             }
 ​
             return false
         }
 ​
         this.time = nowTime
 ​
         // determine whether the currentRecord record already exists, and store it in recordList.
         if (this.currentRecord) {
             this.recordList.push(this.currentRecord)
             // after adding records, the redo records should be emptied.
             this.redoList.splice(0, this.redoList.length)
         }
 ​
         try {
             // convert json to string storage
             this.currentRecord = JSON.stringify(record)
         } catch (error) {
             return
         }
 ​
         // store a maximum of 30 records. If more than that, delete the previous records.
         if (this.recordList.length > 30) {
             this.recordList.unshift()
         }
         return true
     }
 ​
     undo() {
         // if there is no record, return false
         if (this.recordList.length === 0) {
             return null
         }
 ​
         const record = this.recordList.pop()
 ​
         // add the current record to the redo record
         if (this.currentRecord) {
             this.redoList.push(this.currentRecord)
         }
 ​
         // discard the current record to prevent repeated additions
         this.currentRecord = ''
         return JSON.parse(record as string) as PageData
     }
 ​
     redo() {
         // if no record is redone, return false
         if (this.redoList.length === 0) {
             return null
         }
 ​
         const record = this.redoList.pop()
         // add to the redo record
         if (this.currentRecord) {
             this.recordList.push(this.currentRecord)
         }
 ​
         // discard the current record to prevent repeated additions
         this.currentRecord = ''
         return JSON.parse(record as string) as PageData
     }
 }
Exit mobile version