中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么用Immutable.js實現撤銷重做功能

發布時間:2022-03-14 15:23:15 來源:億速云 閱讀:125 作者:iii 欄目:web開發

這篇文章主要介紹了怎么用Immutable.js實現撤銷重做功能的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么用Immutable.js實現撤銷重做功能文章都會有所收獲,下面我們一起來看看吧。

第一步:確定哪些狀態需要歷史記錄,創建自定義的 State 類

并非所有的狀態都需要歷史記錄。許多狀態是非常瑣碎的,尤其是一些與鼠標或者鍵盤交互相關的狀態,例如在畫圖工具中拖拽一個圖形時我們需要設置一個「正在進行拖拽」的標記,頁面會根據該標記顯示對應的拖拽提示,顯然該拖拽標記不應該出現在歷史記錄中;而另一些狀態無法被撤銷或是不需要被撤銷,例如網頁窗口大小,向后臺發送過的請求列表等。

排除那些不需要歷史記錄的狀態,我們將剩下的狀態用 Immutable Record 封裝起來,并定義 State 類:

// State.ts

import { Record, List, Set } from 'immutable'

const StateRecord = Record({

  items: List<Item>

  transform: d3.ZoomTransform

  selection: number

})

// 用類封裝,便于書寫 TypeScript,注意這里最好使用Immutable 4.0 以上的版本

export default class State extends StateRecord {}

這里我們的例子是一個簡易的在線畫圖工具,所以上面的 State 類中包含了三個字段,items 用來記錄已經繪制的圖形,transform 用來記錄畫板的平移和縮放狀態,selection 則表示目前選中的圖形的 ID。而畫圖工具中的其他狀態,例如圖形繪制預覽,自動對齊配置,操作提示文本等,則沒有放在 State 類中。

第二步:定義 Action 基類,并為每種不同的操作創建對應的 Action 子類

與 redux-undo 不同的是,我們仍然采用命令模式:定義基類 Action,所有對 State 的操作都被封裝為一個 Action 的實例;定義若干 Action 的子類,對應于不同類型的操作。

在 TypeScript 中,Action 基類用 Abstract Class 來定義比較方便。

// actions/index.ts

export default abstract class Action {

  abstract next(state: State): State

  abstract prev(state: State): State

  prepare(appHistory: AppHistory): AppHistory { return appHistory }

  getMessage() { return this.constructor.name }

}

Action 對象的 next 方法用來計算「下一個狀態」,prev 方法用來計算「上一個狀態」。getMessage 方法用來獲取 Action 對象的簡短描述。通過 getMessage 方法,我們可以將用戶的操作記錄顯示在頁面上,讓用戶更方便地了解最近發生了什么。prepare 方法用來在 Action 第一次被應用之前,使其「準備好」,AppHistory 的定義在本文后面會給出。

Action 子類舉例

下面的 AddItemAction 是一個典型的 Action 子類,用于表達「添加一個新的圖形」。

// actions/AddItemAction.ts

export default class AddItemAction extends Action {

  newItem: Item

  prevSelection: number

  constructor(newItem: Item) {

    super()

    this.newItem = newItem

  }

  prepare(history: AppHistory) {

    // 創建新的圖形后會自動選中該圖形,為了使得撤銷該操作時 state.selection 變為原來的值

    // prepare 方法中讀取了「添加圖形之前 selection 的值」并保存到 this.prevSelection

    this.prevSelection = history.state.selection

    return history

  }

  next(state: State) {

    return state

      .setIn(['items', this.newItem.id], this.newItem)

      .set('selection', this.newItemId)

  }

  prev(state: State) {

    return state

      .deleteIn(['items', this.newItem.id])

      .set('selection', this.prevSelection)

  }

  getMessage() { return &mdash;&mdash;Add item ${this.newItem.id}&mdash;&mdash; }

}

運行時行為

應用運行時,用戶交互產生一個 Action 流,每次產生 Action 對象時,我們調用該對象的 next 方法來計算后一個狀態,然后將該 action 保存到一個列表中以備后用;用戶進行撤銷操作時,我們從 action 列表中取出最近一個 Action 并調用其 prev 方法。應用運行時,next/prev 方法被調用的情況大致如下:

// initState 是一開始就給定的應用初始狀態

// 某一時刻,用戶交互產生了 action1 ...

state1 = action1.next(initState)

// 又一個時刻,用戶交互產生了 action2 ...

state2 = action2.next(state1)

// 同樣的,action3也出現了 ...

state3 = action3.next(state2)

// 用戶進行撤銷,此時我們需要調用最近一個action的prev方法

state4 = action3.prev(state3)

// 如果再次進行撤銷,我們從action列表中取出對應的action,調用其prev方法

state5 = action2.prev(state4)

// 重做的時候,取出最近一個被撤銷的action,調用其next方法

state6 = action2.next(state5)

Applied-Action

為了方便后面的說明,我們對 Applied-Action 進行一個簡單的定義:Applied-Action 是指那些操作結果已經反映在當前應用狀態中的 action;當 action 的 next 方法執行時,該 action 變為 applied;當 prev 方法被執行時,該 action 變為 unapplied。

關于“怎么用Immutable.js實現撤銷重做功能”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“怎么用Immutable.js實現撤銷重做功能”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

成安县| 出国| 中江县| 工布江达县| 义乌市| 崇明县| 依兰县| 内乡县| 龙门县| 张家界市| 长春市| 闽侯县| 德钦县| 新营市| 句容市| 青冈县| 左权县| 石嘴山市| 阿坝县| 那坡县| 商河县| 峨山| 沾益县| 濉溪县| 天水市| 西充县| 灵丘县| 瑞丽市| 靖州| 江阴市| 新丰县| 岐山县| 特克斯县| 泰安市| 北海市| 汉源县| 五峰| 富源县| 肇庆市| 江北区| 三台县|