ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

GrapesJS UndoManager 模块 API 完全指南:撤销/重做堆栈管理实战

GrapesJS UndoManager 模块 API 完全指南:撤销/重做堆栈管理实战 GrapesJS UndoManager 模块 API 完全指南撤销/重做堆栈管理实战【免费下载链接】grapesjsFree and Open source Web Builder Framework. Next generation tool for building templates without coding项目地址: https://gitcode.com/GitHub_Trending/gr/grapesjsGrapesJS 的 UndoManager 模块负责管理画布Canvas中一系列更改操作的历史堆栈为组件增删改、CSS 规则调整等提供撤销Undo与重做Redo能力。本文以 docs/api/undo_manager.md 中定义的 API 为骨架结合 模块源码、配置定义 与 单元测试系统讲解该模块的配置参数、全部公开方法及底层跟踪机制读完即可在自己的插件或项目中熟练控制撤销/重做流程。模块概览与实例获取UndoManager 是 GrapesJS 编辑器内置的核心模块它基于backbone-undo库对画布内的 Model / Collection 变更进行追踪并将变更记录到堆栈中。编辑器实例化后通过以下方式获取模块句柄const um editor.UndoManager;从源码看该模块继承自Module基类在 编辑器模型 中以get UndoManager()的形式对外暴露um即 UndoManagerModule 的实例。它默认处于启用状态传入undoManager: false时模块被标记为禁用堆栈长度会被置为 0见 index.ts#L53-L55所有跟踪行为随之失效。配置参数编辑器级配置入口在初始化编辑器时通过undoManager配置项传入配置对象或布尔值见 editor/config/config.ts#L305-L308const editor grapesjs.init({ container: #gjs, undoManager: { maximumStackLength: 500, trackSelection: true, }, });默认值为空对象{}见 editor/config/config.ts#L494即全部使用内置默认值。支持的配置项根据 undo_manager/config.ts 的类型定义配置项如下配置项类型默认值说明maximumStackLengthnumber500撤销堆栈最多保存的操作项数量超过后最旧的操作会被丢弃trackSelectionbooleantrue是否跟踪组件选择selection变化使其也可被撤销/重做其中trackSelection的实现体现在 index.ts#L155-L158模块加载完成后postLoad若配置开启且模块未禁用会自动把em.get(selected)集合注册到跟踪器中对应测试用例见 undo_manager 测试中的 Selection tracking 小节。完整禁用 UndoManager将undoManager设为false即可完全关闭撤销功能const editor grapesjs.init({ container: #gjs, undoManager: false, });此时um.isDisabled为trueadd、remove、removeAll等方法直接短路返回见 index.ts#L175-L204hasUndo()恒为false、堆栈保持为空。这一行为在测试Disabled undo manager does not track changes中有明确验证test/specs/undo_manager/index.ts#L28-L42。核心 API 详解以下方法均通过editor.UndoManager实例调用除特别说明外返回this因此支持链式调用。getConfig()获取当前模块的配置对象包含默认值合并结果const config um.getConfig(); console.log(config.maximumStackLength); // 500实体跟踪管理add(entity)将一个实体Backbone Model 或 Collection注册到跟踪器中此后该实体及其包含的变更会被记录um.add(someModelOrCollection);注意新建的组件Components和 CSS 规则CSSRules会被自动加入跟踪无需手动调用add见 index.ts#L168-L179 的注释说明。这一点在测试中得到了印证——测试直接对wrapper追加组件、对editor.Css添加规则后um.hasUndo()立即为truetest/specs/undo_manager/index.ts#L45-L57、#L138-L152。remove(entity)移除并停止跟踪指定实体um.remove(someModelOrCollection);removeAll()移除全部已注册实体um.removeAll();isRegistered(obj)返回布尔值用于判断实体当前是否处于跟踪状态um.isRegistered(someModelOrCollection); // true | false其底层通过this.getInstance().objectRegistry.isRegistered(obj)实现index.ts#L300-L302。跟踪开关start()开始/恢复跟踪变更stop()停止跟踪变更。两者通常成对使用例如在执行大量一次性初始化操作时临时关闭跟踪um.stop(); // 此处产生的变更不会被记录 um.start();底层分别对应backbone-undo的startTracking()与stopTracking()index.ts#L212-L225。撤销与重做undo()撤销最近一次变更redo()重做最近一次被撤销的变更。二者均接受一个可选布尔参数all默认值为true表示一次调用是否应一次性回退/重放全部堆栈项um.undo(); // 撤销最近一次或全部操作 um.redo(); // 重做最近一次或全部操作 um.undo(false); // 仅回退一步 um.redo(false); // 仅前进一步值得注意的是源码在调用底层方法前会检查!em.isEditing()index.ts#L234-L238、#L257-L261即当富文本/内联编辑器处于编辑状态时不会执行撤销/重做以避免干扰正在进行的文本编辑。undoAll()与redoAll()则分别撤销/重做全部变更不带步数控制um.undoAll(); um.redoAll();状态查询hasUndo()判断堆栈中是否存在可撤销的操作hasRedo()判断是否存在可重做的操作if (um.hasUndo()) um.undo(); if (um.hasRedo()) um.redo();底层调用isAvailable(undo)/isAvailable(redo)index.ts#L280-L292。测试中的初始状态断言为新建编辑器、清空堆栈后二者均为false且堆栈长度为 0test/specs/undo_manager/index.ts#L22-L26。堆栈访问getStack()返回当前更改堆栈。官方文档描述返回类型为Collection实际实现直接返回底层backbone-undo的this.um.stackindex.ts#L311-L313可以按集合方式遍历const stack um.getStack(); stack.each((item) { // 处理每条历史记录 });如需将一次批量操作如一次 append 多个组件视为单个撤销动作可使用源码中的getStackGroup()私有方法——它依据magicFusionIndex对相邻操作分组返回去重后的列表index.ts#L326-L339。测试Grouped component additions are treated as one undo action验证了该行为一次wrapper.append(div1/divdiv2/div)后getStackGroup()长度为 1且单次um.undo()即可移除两个组件test/specs/undo_manager/index.ts#L127-L135。skip()临时关闭跟踪skip(clb)在回调执行期间临时停止跟踪回调结束后恢复原有跟踪状态um.skip(() { // 此处的变更不会被记录到撤销堆栈 component.set(content, new value); });源码实现会先判断当前是否处于跟踪状态若正在跟踪则先stop()执行回调后再start()index.ts#L349-L355。编辑器层面的 editor.skip() 同样委托给um.skip()用于执行操作但不触发存储与撤销的场景。clear()清空堆栈clear()清空全部历史记录常用于开始一段新操作前重置状态um.clear();返回this。模块销毁时destroy()也会执行this.clear().removeAll()index.ts#L420-L422。底层跟踪机制与调用链基于 backbone-undo 的类型化跟踪模块在构造函数中创建底层UndoManager实例track: true, register: []并通过changeUndoType注册了四种变更类型index.ts#L57-L143change模型属性变化。通过condition判断实体是否带有_undo标记布尔值或属性名数组支持_undoexc排除属性on回调比较previousAttributes()与toJSON({ fromUndo: true })生成{ object, before, after }记录。add向已注册集合添加模型记录{ object: collection, after: model }。remove从已注册集合移除模型记录{ object: collection, before: model }。reset集合重置记录前后完整模型列表并提供对应的undo/redo回调执行collection.reset。同时hasSkip(opts)检测到avoidStore、noUndo、partial任一选项时跳过记录index.ts#L40。这意味着在业务代码中任何set/append操作都可以通过{ noUndo: true }选项明确排除在撤销历史之外comp.set(content, no undo content, { noUndo: true });对应测试Skipping undo for component modification验证了该行为——带noUndo的修改不会被um.undo()回退test/specs/undo_manager/index.ts#L285-L301。事件联动模块监听底层undo/redo事件触发已选中组件的rerender:layer重渲染index.ts#L145-L147并将事件转发为编辑器级事件。对应的事件枚举定义在 editor/types.ts#L138-L149editor.on(undo, () { console.log(Undo executed); }); editor.on(redo, () { console.log(Redo executed); });完整实战示例下面是一个覆盖跟踪—操作—撤销/重做—跳过全流程的示例const editor grapesjs.init({ container: #gjs, undoManager: { maximumStackLength: 500, trackSelection: true, }, }); const um editor.UndoManager; // 1. 初始状态无撤销、无重做、堆栈为空 console.log(um.hasUndo(), um.hasRedo(), um.getStack().length); // false false 0 // 2. 添加组件新组件自动被跟踪 const wrapper editor.getWrapper(); wrapper.append(div classboxHello/div); console.log(um.hasUndo()); // true // 3. 撤销/重做 um.undo(); // 组件被移除 um.redo(); // 组件重新出现 // 4. 临时跳过跟踪批量导入时不产生历史记录 um.skip(() { wrapper.append(spanA/spanspanB/span); }); console.log(um.hasUndo()); // falseskip 内的操作未入栈 // 5. 指定 noUndo 排除单个操作 wrapper.append(pundoable/p); wrapper.components().at(0).set(content, x, { noUndo: true }); // 6. 清空历史开启新一轮操作 um.clear();注意事项与限制自动跟踪范围新增的组件与 CSS 规则会自动注册但并非所有模块如 Asset Manager、设备切换、面板可见性都默认接入撤销系统。测试文件中以describe.skip标记的Asset Manager changes与Editor states changes小节test/specs/undo_manager/index.ts#L187-L261表明这些场景的撤销支持尚在规划中不应假设其行为可用。编辑态保护富文本编辑过程中调用undo()/redo()会被!em.isEditing()守卫拦截编辑完成后才能正常撤销/重做。堆栈上限maximumStackLength默认 500超限后最早记录会被挤出长期运行的高频操作编辑器建议评估该上限是否满足需求。skip()与noUndo是两套独立机制skip()从源头停止跟踪适合批量导入noUndo/avoidStore/partial选项则作用于单次操作适合精确排除个别变更。禁用后的行为undoManager: false时模块整体失效add、remove、removeAll、start、stop、undo系列及clear均返回this但不产生任何效果。如需查阅更多编辑器 API可参考 docs/api/editor.mdUndoManager 模块的完整实现位于 packages/core/src/undo_manager/index.ts配置定义见 packages/core/src/undo_manager/config.ts全部行为均有对应的 单元测试 可作参照。【免费下载链接】grapesjsFree and Open source Web Builder Framework. Next generation tool for building templates without coding项目地址: https://gitcode.com/GitHub_Trending/gr/grapesjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表