当前位置:首页 > JavaScript

js 实现撤销重做

2026-03-15 22:54:53JavaScript

撤销重做的基本原理

撤销重做功能通常通过维护两个栈来实现:一个用于撤销(undoStack),一个用于重做(redoStack)。每次用户操作时,将当前状态保存到撤销栈中。执行撤销操作时,从撤销栈弹出状态并压入重做栈;执行重做操作时,从重做栈弹出状态并压入撤销栈。

实现步骤

定义状态管理类

创建一个类来管理状态和操作。初始化时设置空栈和当前状态。

class UndoRedoManager {
  constructor(initialState) {
    this.undoStack = [];
    this.redoStack = [];
    this.currentState = initialState;
  }
}

添加状态更新方法

当用户执行操作时,调用此方法将新状态保存到撤销栈中,并清空重做栈。

updateState(newState) {
  this.undoStack.push(this.currentState);
  this.currentState = newState;
  this.redoStack = [];
}

实现撤销功能

从撤销栈弹出最近的状态,保存到重做栈,并恢复为当前状态。

js 实现撤销重做

undo() {
  if (this.undoStack.length === 0) return false;
  this.redoStack.push(this.currentState);
  this.currentState = this.undoStack.pop();
  return true;
}

实现重做功能

从重做栈弹出最近的状态,保存到撤销栈,并恢复为当前状态。

redo() {
  if (this.redoStack.length === 0) return false;
  this.undoStack.push(this.currentState);
  this.currentState = this.redoStack.pop();
  return true;
}

完整代码示例

class UndoRedoManager {
  constructor(initialState) {
    this.undoStack = [];
    this.redoStack = [];
    this.currentState = initialState;
  }

  updateState(newState) {
    this.undoStack.push(this.currentState);
    this.currentState = newState;
    this.redoStack = [];
  }

  undo() {
    if (this.undoStack.length === 0) return false;
    this.redoStack.push(this.currentState);
    this.currentState = this.undoStack.pop();
    return true;
  }

  redo() {
    if (this.redoStack.length === 0) return false;
    this.undoStack.push(this.currentState);
    this.currentState = this.redoStack.pop();
    return true;
  }
}

使用示例

const manager = new UndoRedoManager({ text: '' });

manager.updateState({ text: 'Hello' });
console.log(manager.currentState); // { text: 'Hello' }

manager.updateState({ text: 'Hello World' });
console.log(manager.currentState); // { text: 'Hello World' }

manager.undo();
console.log(manager.currentState); // { text: 'Hello' }

manager.redo();
console.log(manager.currentState); // { text: 'Hello World' }

优化建议

对于大型应用或频繁状态更新的场景,可以考虑以下优化:

限制栈大小

js 实现撤销重做

防止内存无限增长,可以设置栈的最大长度。

constructor(initialState, maxStackSize = 100) {
  this.maxStackSize = maxStackSize;
  // ...其余初始化代码
}

updateState(newState) {
  if (this.undoStack.length >= this.maxStackSize) {
    this.undoStack.shift();
  }
  // ...其余代码
}

使用不可变数据

结合Immutable.js等库,可以更高效地管理状态变化和内存使用。

import { Map } from 'immutable';

const manager = new UndoRedoManager(Map({ text: '' }));
manager.updateState(Map({ text: 'Hello' }));

批量操作处理

对于连续操作,可以合并为单次撤销重做单元。

startBatch() {
  this.batch = [];
}

endBatch() {
  if (this.batch.length > 0) {
    this.undoStack.push(this.batch);
    this.redoStack = [];
  }
  this.batch = null;
}

updateStateInBatch(newState) {
  if (this.batch) {
    this.batch.push(this.currentState);
    this.currentState = newState;
  } else {
    this.updateState(newState);
  }
}

标签: 重做js
分享给朋友:

相关文章

js实现瀑布流

js实现瀑布流

实现瀑布流布局 瀑布流布局是一种常见的网页布局方式,常用于图片展示、商品列表等场景。以下是使用 JavaScript 实现瀑布流布局的几种方法。 纯 JavaScript 实现 通过计算元素的位置和…

js实现抽奖

js实现抽奖

实现抽奖功能的基本思路 抽奖功能的核心是随机选择奖项并展示结果。可以通过数组存储奖项,利用随机数生成索引,最后通过动画增强用户体验。 准备奖项数据 定义一个数组存储奖项信息,每个奖项可以包含名称、图…

jquery js

jquery js

jQuery 简介 jQuery 是一个快速、简洁的 JavaScript 库,简化了 HTML 文档遍历、事件处理、动画和 Ajax 交互。它兼容多种浏览器,提供易于使用的 API,使开发者能够更高…

js实现搜索

js实现搜索

实现搜索功能的方法 在JavaScript中实现搜索功能可以通过多种方式完成,以下是几种常见的实现方法。 使用数组的filter方法 通过数组的filter方法可以筛选出符合条件的数据项。假设有一个…

js计算器的实现

js计算器的实现

实现基础结构 HTML部分需要创建计算器的基本框架,包含显示区域和按钮。使用<div>容器包裹整个计算器,内部设置一个显示屏和多个按钮。 <div class="calculato…

js实现按钮点击

js实现按钮点击

实现按钮点击的JavaScript方法 HTML按钮元素 在HTML中创建按钮元素,为其添加id或class以便JavaScript选择: <button id="myButton">点…