vue3 实现历史步骤记录

通过vueuse中的 useManualRefHistory,快速实现历史操作记录

所需环境:

  • vue

实现目标

  • 历史记录
  • 撤销
  • 重做
  • 记录覆盖

代码原理

把键盘监听事件挂载在document上,当键盘事件发生时,依次匹配事先订阅的快捷键/单按键事件,
如果有匹配到对应的订阅,则进行事件回调,并且停止键盘事件的回调。按下的按键进行转换,把mac/win的键盘差异进行了兼容

实现效果

差两个视频

vue历史记录实战

核心代码

import {ref} from 'vue';
import {useManualRefHistory} from '@vueuse/core';

export enum ActionEnum {
    INIT = '加载',
    ADD = '添加<{element}>',
    RESIZE = '修改<{element}>尺寸',
    ROTATE = '旋转<{element}>',
    REMOVE = '删除<{element}>',
    PASTE = '粘贴<{element}>',
    CUT = '剪切<{element}>',
    CLEAR = '清空面板',
    MOVE = '移动<{element}>',
    BATCH_MOVE = '移动<多个元素>',
    UPDATE_STYLE = '修改<{element}>的[{content}]',
    BATCH_UPDATE_STYLE = '修改<多个元素>的[{content}]',
}

let max = 50;

export interface Snapshot {
    elementList?: any[]
    content?: string
    action: ActionEnum,
    type?: 'Element' | 'PANEL'
}

const historyRecord = ref<Snapshot>({} as Snapshot);
const {
    undoStack,
    redoStack,
    commit,
    history,
    undo,
    redo,
    clear,
    canUndo,
    canRedo
} = useManualRefHistory(historyRecord, {capacity: max});

/**
 * 初始化记录
 * @param elementList
 */
function init(elementList: any[]) {
    record(<Snapshot>{
        type: 'PANEL',
        action: ActionEnum.INIT,
        elementList
    });
    clear();
}

/**
 * 记录历史操作
 * @param snapshot
 */
function record(snapshot: Snapshot) {
    let action = snapshot.action as any;
    let label = '';
    if (snapshot.elementList) {
        for (let myElement of snapshot.elementList) {
            label = label + myElement.label + ',';
        }
        label = label.slice(0, -1)
    } else {
        label = '面板';
    }

    if (action == ActionEnum.UPDATE_STYLE) {
        if (snapshot.elementList != null) {
            action = action.replace('{element}', label).replace('{content}', snapshot.content);
        } else {
            action = action.replace('{element}', label).replace('{content}', snapshot.content);
        }
    } else if ([ActionEnum.REMOVE, ActionEnum.ADD, ActionEnum.RESIZE, ActionEnum.ROTATE, ActionEnum.MOVE].includes(action)) {
        action = action.replace('{element}', label);
    }

    snapshot.action = action;

    // 记录历史
    historyRecord.value = JSON.parse(JSON.stringify(snapshot));
    commit();
}

/**
 * 撤销
 */
function undoPanel() {
    if (!canUndo.value) {
        return;
    }
    undo();
    return historyRecord.value.elementList;
}

/**
 * 重做
 */
function redoPanel() {
    if (!canRedo.value) {
        return;
    }
    redo();
    return historyRecord.value.elementList;
}

export {
    init,
    record,
    canUndo,
    canRedo,
    undoStack,
    redoStack,
    undoPanel,
    redoPanel,
    redo,
    history,
    clear
};

使用示例


const elementList = ref<any[]>([{}])

// 记录日志
record(<Snapshot>{
    type: 'Element',
    action: ActionEnum.RESIZE,
    elementList: elementList.value
});

// 撤销
elementList.value = JSON.parse(JSON.stringify(undoPanel()));

// 重做
elementList.value = JSON.parse(JSON.stringify(redoPanel()));

代码仓库

代码仓库:github

代码仓库:gitee

实战项目:MyPrint

操作简单,组件丰富的一站式打印解决方案打印设计器

体验地址:前往

代码仓库:github

代码仓库:gitee

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值