当前位置:首页 > 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实现轮播

实现轮播图的基本思路 轮播图的核心逻辑是通过定时切换展示的图片或内容,通常结合左右滑动按钮和指示器(小圆点)增强交互性。以下是基于原生JavaScript的实现方法。 HTML结构 构建轮播图的HT…

js实现复制到剪贴板

js实现复制到剪贴板

使用document.execCommand方法(传统方式,已废弃但部分浏览器仍支持) 该方法适用于旧版浏览器,但已被标记为废弃。执行前需确保文本已被选中: function copyToClipb…

js实现路由

js实现路由

js实现路由的方法 在JavaScript中实现路由功能可以通过多种方式完成,以下是几种常见的方法: 使用原生JavaScript实现路由 通过监听window.onhashchange事件来实现基…

js实现排序

js实现排序

数组排序方法 JavaScript提供了内置的sort()方法用于数组排序。默认情况下,sort()将元素转换为字符串并按照Unicode码点排序。对于数字排序,需传入比较函数。 const num…

js实现文件夹

js实现文件夹

使用JavaScript创建文件夹 在浏览器端的JavaScript中无法直接操作文件系统创建文件夹,这是出于安全考虑。但在Node.js环境中可以通过文件系统模块(fs)实现。 Node.js中使…

js实现乘法

js实现乘法

实现乘法运算的方法 在JavaScript中实现乘法运算可以通过多种方式完成,以下列举几种常见方法: 基础运算符 直接使用乘法运算符*是最简单的方式: let result = 3 * 5; //…