js实现封装历史记录功能,支持撤回、重做、清空等操作,可在其他任何需要历史记录的系统中使用 。

实现历史记录class版

// 最大历史栈长度
const MAX_HISTORY_LENGTH = 100;
 
// 获取数组最后一个元素
const last = (arr) => arr[arr.length - 1];
// 清空数组
const clear = (arr) => arr.splice(0, arr.length);
 
class History {
    constructor(maxLength = MAX_HISTORY_LENGTH) {
        // 历史记录栈
        this.stack = [];
        // 撤销栈
        this.undoStack = [];
        // 最新的值
        this.currentValue = null;
        // 最大历史栈长度
        this.maxLength = maxLength;
    }
 
    /**
     * 是否满
     */
    isFull() {
        return this.stack.length >= this.maxLength;
    }
 
    /**
     * 添加历史记录
     * @param {*} value 历史记录值
     */
    push(value) {
        this.stack.push(value);
        this.undoStack = [];
        this.currentValue = value;
        if (this.stack.length > this.maxLength) {
            this.stack.splice(0, 1);
        }
    }
 
    /**
     * 撤销
     */
    undo() {
        if (this.stack.length === 0) {
            return;
        }
        const value = this.stack.pop();
        this.undoStack.push([value]);
        this.currentValue = last(this.stack);
    }
 
    /**
     * 重做
     */
    redo() {
        if (this.undoStack.length === 0) {
            return;
        }
        const valueList = this.undoStack.pop();
        this.stack.push(...valueList);
        this.currentValue = last(this.stack);
    }
 
    /**
     * 清空历史栈
     */
    clear() {
        this.undoStack.push([ ...this.stack ]);
        this.stack = [];
    }
}
 
export default History;

简化版本

 

构造函数版

  • 历史栈为私有属性,避免被外部直接修改导致出错
/**
 * 历史记录构造函数版(栈为私有属性)
 * @param {number} maxLength 最大长度
 */
function HistoryFun (maxLength = MAX_HISTORY_LENGTH) {
    // 历史记录栈
    const stack = [];
    // 撤销栈
    const undoStack = [];
    // 最新的值
    this.currentValue = null;
 
    /**
     * 满
     */
    this.isFull = () => {
        return stack.length >= maxLength;
    };
 
    /**
     * 历史栈长度
     */
    this.getLength = () => {
        return stack.length;
    }
 
    /**
     * 获取历史栈
     */
    this.getHistoryStack = () => {
        return [ ...stack ];
    }
 
    /**
     * 获取撤销栈
     */
        this.getUndoStack = () => {
        return [ ...undoStack ];
    }
    
    /**
     * 添加历史记录
     * @param {*} value 历史记录值
     */
    this.push = (value) => {
        stack.push(value);
        clear(undoStack);
        this.currentValue = value;
        if (stack.length > this.maxLength) {
            stack.splice(0, 1);
        }
    };
 
    /**
     * 撤销
     */
    this.undo = () => {
        if (stack.length === 0) {
            return;
        }
        const value = stack.pop();
        undoStack.push([value]);
        this.currentValue = last(stack);
    };
 
    /**
     * 重做
     */
    this.redo = () => {
        if (undoStack.length === 0) {
            return;
        }
        const valueList = undoStack.pop();
        stack.push(...valueList);
        this.currentValue = last(stack);
    };
 
    /**
     * 清空历史栈
     */
    this.clear = () => {
        undoStack.push([...stack]);
        clear(stack);
    };
}

使用

const history = new History(10);
 
history.push(1); // [1]  []
history.push(2); // [1,2]  []
history.push(3); // [1,2,3]  []
history.undo(); // [1,2]  [[3]]
history.undo(); // [1]  [[3],[2]]
history.redo(); // [1,2]  [[3]]
history.clear(); // []  [[3], [1,2]]
history.redo(); // [1,2]  [[3]]
history.redo(); // [1,2,3]  []

演示

为了方便理解做了一个demo,通过点击按钮进行历史记录的操作操作。

链接如下:历史记录演示demo

扩展阅读