欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vuex實現歷史記錄的示例代碼

 更新時間:2021年05月12日 08:36:05   作者:KwokRonny  
這篇文章主要介紹了vuex實現歷史記錄的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

最近自研著一個可視化操作平臺,其中涉及到用戶操作后可撤銷或重做,在網上搜了一些解決思路,完善自己所設想的解決思路。

歷史記錄需求的要點

  • 可存儲在 localStorage 中
  • 可多次撤銷或多次重做
  • 點擊列表中的一項,將歷史倒退或前進至指定位置

看似簡單的需求,在基礎建設設計上的錯誤,亦會在未來導致更多的工作量。所以結合上面兩點的要求,發(fā)現 vuex 的基本思路非常適合完成這個需求,redux 同樣。

實現思路

此項目用了 typescript 來加強代碼的嚴謹性,方便日后維護,大家簡單看個思路。

1. 先定義歷史記錄的數據結構

interface HistoryItem {
  timestrap: number; // 記錄時間戳
  name: string; // 記錄名稱
  redo: string; // 重做Mutation
  undo: string; // 撤銷Mutation
  redoParams: any[]; // 重做Mutation提交參數
  undoParams: any[]; // 撤銷Mutation提交參數
}

interface HistoryStatus {
  historys: HistoryItem[]; // 記錄history數組
  _currentHistory: number; // 當前節(jié)點索引
}

2. 編寫 History 狀態(tài)模塊

編寫基礎操作history狀態(tài)的vuex module,創(chuàng)建記錄的Mutation,重做和撤銷的Action
一條記錄是包含對這個步驟的執(zhí)行redo操作與撤銷undo操作的。所以在用戶點擊列表其中一項時,應該是循環(huán)回退到當前項的前一項undo,或循環(huán)redo到當前項

所以需要增加一條空記錄,方便用戶點擊空記錄撤銷最初的操作。

運用了vuex-module-decorators 裝飾器,寫更易維護的代碼

import { VuexModule, Module, Mutation, Action } from "vuex-module-decorators";

@Module({ namespaced: true })
export class HistoryModule extends VuexModule<HistoryStatus> implements HistoryStatus {
  /** 
   * 初始化一個空記錄的原因主要是方便列表操作時:
   * 當用戶點擊最早的一條記錄時,可以正常撤銷用戶操作的第一步
  **/
  public historys: HistoryItem[] = [
    {
      name: `打開`,
      timestrap: Date.now(),
      redo: "",
      redoParams: [],
      undo: "",
      undoParams: [],
    },
  ];
  public _currentHistory: number = 0;

  // getter
  get current(){
    return this._currentHistory;
  }

  // getter
  get historyList(): HistoryItem[] {
    return this.historys || [];
  }

  // 創(chuàng)建歷史記錄
  @Mutation
  public CREATE_HISTORY(payload: HistoryItem) {
    if (this._currentHistory < this.historys.length - 1) {
      this.historys = this.historys.slice(0, this._currentHistory);
    }
    // 由于js的深淺拷貝問題,所以在創(chuàng)建時都需要對數據進行深拷貝
    // 想嘗試lodash的clone函數,但發(fā)現好像JSON.stringify的方式clone應該更快的,畢竟我們的數據不存在函數
    // 我這里就先不改了,主要是表達出思路即可
    this.historys.push(_.cloneDeep(payload));
    this._currentHistory = this.historys.length - 1;
  }

  @Mutation
  public SET_CURRENT_HISTORY(index: number) {
    this._currentHistory = index < 0 ? 0 : index;
  }

  // 重做
  @Action
  public RedoHistory(times: number = 1) {
    let { state, commit } = this.context;
    let historys: HistoryItem[] = state.historys;
    let current: number = state._currentHistory;
    if (current + times >= historys.length) return;
    while (times > 0) {
      current++;
      let history = historys[current];
      if (history) {
        commit(history.redo, ...history.redoParams, { root: true });
      }
      times--;
    }
    commit("SET_CURRENT_HISTORY", current);
  }

  // 撤銷
  @Action
  public UndoHistory(times: number = 1) {
    let { state, commit } = this.context;
    let historys: HistoryItem[] = state.historys;
    let current: number = state._currentHistory;
    if (current - times < 0) return;
    while (times > 0) {
      let history = historys[current];
      if (history) {
        commit(history.undo, ...history.undoParams, { root: true });
      }
      times--;
      current--;
    }
    commit("SET_CURRENT_HISTORY", current);
  }
}

3. 編寫可以撤銷或重做的功能

完成上面兩步后,我們就可以編寫各種操作了

編寫對數據基礎操作的Mutation

@Mutation
public CREATE_PAGE(payload: { page: PageItem; index: number }) {
  this.pages.splice(payload.index, 0, _.cloneDeep(payload.page));
  this._currentPage = this.pages.length - 1;
}

@Mutation
public REMOVE_PAGE(id: string) {
  let index = this.pages.findIndex((p) => p.id == id);
  index > -1 && this.pages.splice(index, 1);
  if (this._currentPage == index) {
    this._currentPage = this.pages.length > 0 ? 0 : -1;
  }
}

將基礎操作按要求封裝成帶保存->記錄->執(zhí)行的Action

// 包裝創(chuàng)建頁面函數
@Action
public CreatePage(type: "page" | "dialog") {
  let { state, commit } = this.context;
  
  // 記錄保存即將創(chuàng)建的頁面
  let id = _.uniqueId(type) + Date.now();
  let pageName = pageType[type];
  let page: PageItem = {
    id,
    name: `${pageName}${state.pages.length + 1}`,
    type,
    layers: [],
    style: { width: 720, height: 1280 },
  };

  //創(chuàng)建歷史記錄
  let history: HistoryItem = {
    name: `創(chuàng)建${pageName}`,
    timestrap: Date.now(),
    redo: "Page/CREATE_PAGE",
    redoParams: [{ index: state.pages.length - 1, page }],
    undo: "Page/REMOVE_PAGE",
    undoParams: [id],
  };
  // 保存記錄此歷史記錄
  commit("Histroy/CREATE_HISTORY", history, { root: true });

  commit(history.redo, ...history.redoParams, { root: true });
}

@Action
public RemovePage(id: string) {
  // 記錄保存現場狀態(tài)
  let index = this.pages.findIndex((p) => p.id == id);
  if (index < 0) return;
  let page: PageItem = this.context.state.pages[index];

  //創(chuàng)建歷史記錄
  let history: HistoryItem = {
    name: `刪除 ${page.name}`,
    timestrap: Date.now(),
    redo: "Page/REMOVE_PAGE",
    redoParams: [id],
    undo: "Page/CREATE_PAGE",
    undoParams: [{ page, index }],
  };

  // 保存記錄此歷史記錄
  this.context.commit("Histroy/CREATE_HISTORY", history, { root: true });
  this.context.commit(history.redo, ...history.redoParams, { root: true });
}

以上,撤銷與重做的功能就基本完成了

4. 使用

1. 我們現在只需要在使用時創(chuàng)建或刪除頁面時使用封裝的`Action`后

  private create(type: "page" | "dialog") {
    this.$store.dispatch("Page/CreatePage", type);
  }

  private remove(id: number) {
    this.$store.dispatch("Page/RemovePage", id);
  }

2. 配置全局熱鍵

typescript App.vue

private mounted() {
    let self = this;
    hotkeys("ctrl+z", function (event, handler) {
      self.$store.dispatch("History/UndoHistory");
    });
    hotkeys("ctrl+y", function (event, handler) {
      self.$store.dispatch("History/RedoHistory");
    });
  }

效果

到此這篇關于vuex實現歷史記錄的示例代碼的文章就介紹到這了,更多相關vuex 歷史記錄內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vue.config.js配置報錯ValidationError:?Invalid?options?object解決辦法

    Vue.config.js配置報錯ValidationError:?Invalid?options?object解

    這篇文章主要給大家介紹了關于Vue.config.js配置報錯ValidationError:?Invalid?options?object的解決辦法,主要由于vue.config.js配置文件錯誤導致的,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-02-02
  • vue中子組件的methods中獲取到props中的值方法

    vue中子組件的methods中獲取到props中的值方法

    今天小編就為大家分享一篇vue中子組件的methods中獲取到props中的值方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • Vue3滑動到最右驗證功能實現

    Vue3滑動到最右驗證功能實現

    在登錄頁面需要啟動向右滑塊驗證功能,遇到這樣的需求怎么實現呢,下面小編通過示例代碼給大家分享Vue3滑動到最右驗證功能實現,感興趣的朋友一起看看吧
    2024-06-06
  • 使用Vue3和Echarts?5繪制帶有立體感流線中國地圖(推薦收藏!)

    使用Vue3和Echarts?5繪制帶有立體感流線中國地圖(推薦收藏!)

    最近接到一個需求是做一個中國地圖,下面這篇文章主要給大家介紹了關于如何使用Vue3和Echarts?5繪制帶有立體感流線中國地圖的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • Vue使用Prism實現頁面代碼高亮展示示例

    Vue使用Prism實現頁面代碼高亮展示示例

    這篇文章主要為大家介紹了Vue使用Prism實現頁面代碼高亮展示示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • vue項目如何解決數字計算精度問題

    vue項目如何解決數字計算精度問題

    這篇文章主要介紹了vue項目如何解決數字計算精度問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • vue使用keep-alive保持滾動條位置的實現方法

    vue使用keep-alive保持滾動條位置的實現方法

    這篇文章主要介紹了vue使用keep-alive保持滾動條位置的實現方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • vue3+ts+vant移動端H5項目搭建的實現步驟

    vue3+ts+vant移動端H5項目搭建的實現步驟

    本文主要介紹了vue3+ts+vant移動端H5項目搭建,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • Vue作用域插槽實現方法及作用詳解

    Vue作用域插槽實現方法及作用詳解

    這篇文章主要介紹了Vue作用域插槽實現方法及作用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • antd日期選擇器禁止選擇當天之前的時間操作

    antd日期選擇器禁止選擇當天之前的時間操作

    這篇文章主要介紹了antd日期選擇器禁止選擇當天之前的時間操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10

最新評論