ck-editor5的研究 (6):进一步优化页面刷新时,保存提示的逻辑

article/2025/6/30 21:38:44

文章目录

  • 一、前言
  • 二、实现步骤
    • 1. 第一步: 引入 PendingActions 插件
    • 2. 第二步:注册事件
    • 3. 第三步:点击保存按钮时,控制状态变化
  • 三、测试效果和细节
  • 四、总结


一、前言

在上一篇文章中 ck-editor5的研究 (5):优化-页面离开时提醒保存,顺便了解一下 Editor的生命周期 和 6大编辑器类型 ,我们对离开页面时进行了优化。

但是每次刷新页面,都会有弹窗警告。这篇文章,我们进一步优化,只有当数据发生变化、正在保存中时,刷新页面才进行提示。

实现的效果图大致如下:
在这里插入图片描述


二、实现步骤

大致分成了 3 个步骤,我们仍然使用上一篇文章的目录结构

1. 第一步: 引入 PendingActions 插件

这个插件在 @ckeditor/ckeditor5-core 里面,需要先安装这个依赖

pnpm add @ckeditor/ckeditor5-core@37.1.0

可以看到这个 插件的文档,然后在 ckeditor5.ts 中使用插件:在这里插入图片描述

2. 第二步:注册事件

在demo5/index.vue中,编辑器初始化完成后,注册状态变更事件,这里用到了一个新接口 instance.plugin.get 方法(获取某个插件):
在这里插入图片描述

3. 第三步:点击保存按钮时,控制状态变化

在点击保存按钮时,控制 按钮可点击状态 和 是否保存中状态,同时在 window 对象的 beforeunload 事件中判断状态,决定是否弹窗提示,完整代码如下:

<template><div class="space-y-4"><h1 class="text-xl font-bold">demo5: 优化-页面离开时提醒用户保存信息</h1><!-- TODO 测试控制面板 --><div class="flex gap-2"><buttonid="save"@click="handleSaveButton"class="text-white cursor-pointer rounded border-none bg-blue-500 px-4 py-2 text-[#fff] outline-none":class="{ active: !isDirty, saving: isSaving }">{{ !isDirty ? '数据没变化,无需保存' : isSaving ? '保存中...' : '点击保存' }}</button><div class="text-gray-500 flex items-center text-sm">{{ isSaving ? '保存中......刷新页面有离开提示' : '非保存中,刷新页面不提示' }}</div></div><!-- 编辑器组件 --><ClientOnly><CkEditor5 @ready="handleEditorReady" /></ClientOnly></div>
</template><script setup lang="ts">
import type MyClassicEditor from '@/components/ck/editor5/ckeditor5';let instance: MyClassicEditor | null = null;
const isDirty = ref(false);
const isSaving = ref(false);const handleEditorReady = (editor: MyClassicEditor) => {console.log('editor :>> ', editor);instance = editor;initStatusChangesEvent();
};/*** 初始化2个状态改变的事件 `change:hasAny` 和 `change:data`*/
function initStatusChangesEvent() {// 获取插件const peddingActionPlugin = instance?.plugins.get('PendingActions');// console.log('peddingActionPlugin :>> ', peddingActionPlugin);// 此插件自带一个 `change:hasAny` 事件可以监听是否有动作正在进行中peddingActionPlugin?.on('change:hasAny', () => {updateStatus();});// 编辑器实例对象, 监听 `change:data`(内容变更) 事件, 内容有改变时,才可以点击保存按钮instance?.model.document.on('change:data', () => {isDirty.value = true;updateStatus();});
}/*** 使用`pendingActions.hasAny` 判断是否正在保存中*/
function updateStatus() {if (instance?.plugins.get('PendingActions').hasAny) {isSaving.value = true;} else {isSaving.value = false;}
}/*** 点击保存按钮时,控制状态变化*/
function handleSaveButton(e: Event) {console.log('handleSaveButton');e.preventDefault();const data = instance?.getData();const pendingActions = instance?.plugins.get('PendingActions');// 添加一个保存中状态, 可以使用`pendingActions.hasAny` 判断是否保存中const action = pendingActions?.add('Saving changes');// console.log('action :>> ', action);if (!action) {return;}// 模拟保存中状态, 5秒后移除保存中状态setTimeout(() => {pendingActions?.remove(action);// 如果数据没有变化, 则设置为未修改状态if (data === instance?.getData()) {isDirty.value = false;}updateStatus();}, 5000);
}/*** 注册页面卸载事件, 判断是否有动作正在进行中。决定是否弹窗提醒*/
useEventListener(window, 'beforeunload', (event: BeforeUnloadEvent) => {const pendingActions = instance?.plugins.get('PendingActions');// console.log('pendingActions :>> ', pendingActions);if (pendingActions?.hasAny) {event.preventDefault();}
});
</script><style lang="less" scoped>
// 样式
.active {background-color: #007bff;opacity: 0.5;cursor: not-allowed;pointer-events: none; // 禁止元素触发点击事件
}
.saving {background-color: #007bff;opacity: 0.5;cursor: not-allowed;pointer-events: none;
}
</style>

三、测试效果和细节

在 demo5/index.vue 中测试该组件,可以看到效果:
在这里插入图片描述
可以看到:当数据没有变化时,不需要保存,因此按钮不可点击; 当数据发生变化时,我们通过点击触发手动保存动作(也可以用定时器每隔一段时间自动保存),假如正在保存中,则刷新页面会进行提示。


四、总结

到此为止,我们算是完成了所有优化,增强了用户保存内容的体验,同时又不那么频繁触发弹窗。


http://www.hkcw.cn/article/OHGkXxrykf.shtml

相关文章

手机归属地查询接口如何用Java调用?

一、什么是手机归属地查询接口&#xff1f; 是一种便捷、高效的工具&#xff0c;操作简单&#xff0c;请求速度快。它不仅能够提高用户填写地址的效率&#xff0c;还能帮助企业更好地了解客户需求&#xff0c;制定个性化的营销策略&#xff0c;降低风险。随着移动互联网的发展…

列表推导式(Python)

[表达式 for 变量 in 列表] 注意&#xff1a;in后面不仅可以放列表&#xff0c;还可以放range ()可迭代对象 [表达式 for 变量 in 列表 if 条件]

【机器学习|评价指标4】正预测值(PPV)、负预测值(NPV)、假阴性率(FNR)、假阳性率(FPR)详解,附代码。

【机器学习|评价指标4】正预测值&#xff08;PPV&#xff09;、负预测值&#xff08;NPV&#xff09;、假阴性率&#xff08;FNR&#xff09;、假阳性率&#xff08;FPR&#xff09;详解&#xff0c;附代码。 【机器学习|评价指标4】正预测值&#xff08;PPV&#xff09;、负预…

【Delphi】实现在多显示器时指定程序运行在某个显示器上

在多显示器时代&#xff0c;经常会出现期望将程序运行在某个指定的显示器上&#xff0c;特别是在调试程序的时候&#xff0c;期望切换分辨率&#xff0c;单步调试时&#xff0c;此时容易导致互相卡住&#xff0c;非常不方便&#xff0c;但是通过指定程序运行在不同的显示器上就…

渗透实战PortSwigger Labs AngularJS DOM XSS利用详解

本Lab学习到关于AngularJS的 xss 漏洞利用 直接输入回显页面&#xff0c;但是把<>进了 html 编码了 当我们输入{{11}}&#xff0c;没有当作字符处理&#xff0c;而是执行了 {{}} 是多种前端框架&#xff08;如 Vue、Angular、Django 模板等&#xff09;中常见的模板插值语…

配置刷新技术

FPGA 片上三模冗余( TMR) 设计结合配置刷新( Scrubbing) 的防护方法能够有效地提高系统的抗单粒子翻转性能。 三模冗余的方法利用模块三冗余及三取二自动表决来掩蔽错误&#xff0c;但是如果错误积累到一定程度&#xff0c;导致同时有两个或两个以上模块发生翻转错误&#xff0…

计算机科技笔记: 容错计算机设计05 n模冗余系统 其他复杂结构

目录 NMR变体动态冗余系统混合冗余系统筛除新系统 NMR变体 V是表决器 动态冗余系统 优点像N模并行系统&#xff0c;后边加一个故障检测和系统重构百分之90以上的故障都是瞬时故障&#xff0c;检测到故障重新运行即可如果出现老化&#xff0c;可以用Spare-1替代 混合冗余系…

HealthBench医疗AI评估基准:技术路径与核心价值深度分析(上)

引言:医疗AI评估的新范式 在人工智能技术迅猛发展的当下,医疗AI系统已逐渐从实验室走向临床应用。然而,医疗领域的特殊性要求这些系统不仅需要在技术指标上表现出色,更需要在实际临床场景中展现出可靠、安全且有效的性能。长期以来,医疗AI评估领域面临着三个核心挑战:评…

中国就业人口现状分析与未来趋势预测

目录 1、核心摘要 2、就业人口总量与趋势 就业人口规模 产业结构变化 3、未来就业趋势 2030年就业变革 人口结构影响 技能需求变化 4、年龄结构与老龄化影响 老龄化现状 抚养比变化 6、老龄化经济影响 消费结构变化 创新活力 7、行业分布与数字经济 行业就业结…

三种经典算法优化无线传感器网络(WSN)覆盖(SSA-WSN、PSO-WSN、GWO-WSN),MATLAB代码实现

三种经典算法优化无线传感器网络(WSN)覆盖&#xff08;SSA-WSN、PSO-WSN、GWO-WSN&#xff09;&#xff0c;MATLAB代码实现 目录 三种经典算法优化无线传感器网络(WSN)覆盖&#xff08;SSA-WSN、PSO-WSN、GWO-WSN&#xff09;&#xff0c;MATLAB代码实现效果一览基本介绍程序设…

SQL Transactions(事务)、隔离机制

目录 Why Transactions? Example: Bad Interaction Transactions ACID Transactions COMMIT ROLLBACK How the Transaction Log Works How Data Is Stored Example: Interacting Processes Interleaving of Statements Example: Strange Interleaving Fixing the…

Linux(10)——第二个小程序(自制shell)

目录 ​编辑 一、引言与动机 &#x1f4dd;背景 &#x1f4dd;主要内容概括 二、全局数据 三、环境变量的初始化 ✅ 代码实现 四、构造动态提示符 ✅ 打印提示符函数 ✅ 提示符生成函数 ✅获取用户名函数 ✅获取主机名函数 ✅获取当前目录名函数 五、命令的读取与…

MySQL:视图+用户管理+访问+连接池原理

一、视图 视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff08;相当于是把查询的内容当成一个临时表来使用&#xff09;&#xff0c;视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表&#xff0c;基表的数据变化也会影响到视图。 1.1 为…

【2025年B卷】华为OD-100分-字符串重新排列、字符串重新排序

专栏订阅🔗 -> 赠送OJ在线评测 字符串重新排列、字符串重新排序 问题描述 给定一个字符串 s s s,

LearnOpenGL-笔记-其十三

PBR(Physically Based Rendering) 什么是基于物理的渲染&#xff1f;简单地说&#xff0c;还记得我们之前学习的法线贴图的内容吗&#xff1f;我们希望不修改物体实际几何形状的前提下去修改表面的法线方向来实现不同的光照效果&#xff0c;实现这个内容的基础就是我们的光照效…

微软PowerBI考试 PL-300学习指南

微软PowerBI考试 PL-300学习指南 Microsoft Power BI 数据分析师学习指南 昨天的投票情况&#xff1a; 技能概览 准备数据 (25-30%) 数据建模 (25-30%) 可视化和分析数据 (25-30%) 管理和保护 Power BI (15–20%) 准备数据 (25-30%) 获取或连接到数据 确定并连接到数据源…

机器学习——集成学习

一、集成学习概念 集成学习: (Ensemble Learning)是一种机器学习范式&#xff0c;它通过构建并结合多个模型来完成学习任务,获得更好的泛化性能。 核心思想&#xff1a;通过组合多个弱学习器来构建一个强学习器。 bagging思想&#xff1a;有放回的抽样&#xff1b;平权投票…

ResNet改进(46):Ghost-ResNet优化卷积神经网络

1.创新点分析 引言 在计算机视觉领域,ResNet是里程碑式的架构,但其计算量较大限制了在资源受限环境的应用。 华为诺亚方舟实验室提出的Ghost模块通过"廉价操作"生成冗余特征图,显著降低了计算成本。 本文将深入解析基于Ghost模块的ResNet实现,展示如何在不显著…

光伏功率预测 | LSTM多变量单步光伏功率预测(Matlab完整源码和数据)

光伏功率预测 | MATLAB实现基于LSTM长短期记忆神经网络的光伏功率预测 目录 光伏功率预测 | MATLAB实现基于LSTM长短期记忆神经网络的光伏功率预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 光伏功率预测 | LSTM多变量单步光伏功率预测&#xff08;Matlab完整源码和…

langGraph多Agent

目录 子图&#xff08;Subgraphs&#xff09;使用子图共享状态模式&#xff08;Shared state schemas&#xff09;不同状态模式&#xff08;Different state schemas&#xff09;添加持久化查看子图状态流式获取子图输出 多智能体系统&#xff08;Multi-agent systems&#xff…