当前位置:首页 > JavaScript

js 实现撤销

2026-03-14 03:49:29JavaScript

撤销功能的实现思路

在JavaScript中实现撤销功能通常需要记录操作历史,并在用户触发撤销时回退到之前的状态。以下是几种常见实现方式:

命令模式实现

使用命令模式封装操作,保存操作历史栈:

js 实现撤销

class CommandManager {
  constructor() {
    this.history = [];
    this.redoStack = [];
  }

  execute(command) {
    command.execute();
    this.history.push(command);
    this.redoStack = [];
  }

  undo() {
    const command = this.history.pop();
    if (command) {
      command.undo();
      this.redoStack.push(command);
    }
  }

  redo() {
    const command = this.redoStack.pop();
    if (command) {
      command.execute();
      this.history.push(command);
    }
  }
}

状态快照实现

保存应用状态的完整快照:

class UndoManager {
  constructor(initialState) {
    this.history = [initialState];
    this.currentIndex = 0;
  }

  get currentState() {
    return this.history[this.currentIndex];
  }

  commit(newState) {
    this.history = this.history.slice(0, this.currentIndex + 1);
    this.history.push(newState);
    this.currentIndex++;
  }

  undo() {
    if (this.currentIndex > 0) {
      this.currentIndex--;
      return this.currentState;
    }
    return null;
  }

  redo() {
    if (this.currentIndex < this.history.length - 1) {
      this.currentIndex++;
      return this.currentState;
    }
    return null;
  }
}

使用Immutable.js优化

对于复杂状态管理,使用不可变数据结构更高效:

js 实现撤销

import { List } from 'immutable';

class ImmutableUndo {
  constructor(initialState) {
    this.history = List([initialState]);
    this.index = 0;
  }

  get current() {
    return this.history.get(this.index);
  }

  commit(newState) {
    this.history = this.history.slice(0, this.index + 1).push(newState);
    this.index++;
  }

  undo() {
    if (this.index > 0) {
      this.index--;
      return this.current;
    }
    return null;
  }

  redo() {
    if (this.index < this.history.size - 1) {
      this.index++;
      return this.current;
    }
    return null;
  }
}

实际应用示例

在文本编辑器中的实现:

class TextEditor {
  constructor() {
    this.text = '';
    this.undoManager = new CommandManager();
  }

  insertText(text, position) {
    const command = {
      execute: () => {
        this.text = this.text.slice(0, position) + text + this.text.slice(position);
      },
      undo: () => {
        this.text = this.text.slice(0, position) + this.text.slice(position + text.length);
      }
    };
    this.undoManager.execute(command);
  }

  undo() {
    this.undoManager.undo();
  }

  redo() {
    this.undoManager.redo();
  }
}

性能优化建议

对于大型应用,考虑以下优化策略:

  • 限制历史记录的最大长度
  • 使用差异算法只存储状态变化而非完整状态
  • 对大型对象使用结构化克隆或序列化
  • 实现节流机制防止高频操作产生过多历史记录

浏览器内置API

现代浏览器支持document.execCommand('undo')document.execCommand('redo'),但仅限于可编辑区域且功能有限,不推荐作为主要解决方案。

标签: js
分享给朋友:

相关文章

js实现动画

js实现动画

使用 CSS 动画与 JavaScript 控制 通过 JavaScript 动态添加或移除 CSS 类来触发动画。CSS 定义关键帧(@keyframes),JavaScript 通过 classL…

js实现文件下载

js实现文件下载

使用 a 标签下载文件 通过动态创建 a 标签并设置 download 属性实现文件下载。适用于已知文件 URL 或 Blob 数据的情况。 function downloadFile(url, f…

js实现选项卡

js实现选项卡

实现选项卡的基本思路 选项卡通常由一组标签和对应的内容面板组成。点击标签时,显示对应的内容面板,隐藏其他面板。实现这一效果需要结合HTML结构、CSS样式和JavaScript交互逻辑。 HTML结…

js实现类

js实现类

JavaScript 实现类的几种方式 JavaScript 是一种基于原型的语言,但在 ES6 之后引入了 class 语法糖,使得实现类更加直观。以下是几种常见的实现方式: 使用构造函数 传统的…

js实现变形

js实现变形

使用 CSS 和 JavaScript 实现元素变形 在 JavaScript 中实现变形效果通常结合 CSS 的 transform 属性,通过动态修改该属性实现元素的旋转、缩放、倾斜或平移。 基…

js实现防洪

js实现防洪

防抖(Debounce)实现 防抖的核心思想是在事件触发后延迟执行回调函数,若在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口调整等场景。 function debounce(func,…