vue 3 富文本字数统计需对齐编辑器生命周期、事件流与响应式更新,核心是监听变化→计算纯文本长度→响应式更新→超限拦截;wangeditor 用 onchange 去标签计数,tiptap 用 onupdate + watch 精准截断,须覆盖粘贴、输入等全路径并做服务端校验。

在 Vue 3 中实现富文本内容变更时的字数统计与超出限制响应式拦截,关键不在于“加个计数器”,而在于把字数逻辑和编辑器生命周期、事件流、响应式更新三者对齐。不同富文本库(如 Tiptap、WangEditor、Quill、TinyMCE)机制差异大,但底层思路一致:监听内容变化 → 实时计算纯文本长度(或按需剔除空格/标签)→ 触发响应式状态更新 → 超限时主动干预(截断/提示/禁用输入)。
基于 WangEditor 的轻量实现(推荐新手)
WangEditor 提供了简洁的 onchange 回调,适合快速落地:
- 在组件中用
ref存储编辑器实例,onMounted初始化; - 配置
customConfig.onchange = (html) => { ... },每次内容变动都触发; - 用正则
html.replace(/]+>/g, '').replace(/\s+/g, '')去除所有 HTML 标签和空白字符,再取.length得有效字数; - 将字数存入
ref(如editorLen),绑定到模板显示; - 当超过
props.maxLength时,调用editor.txt.clear()或editor.txt.html(oldHtml)恢复上一版,并弹出提示。
Tiptap 的响应式集成(推荐中大型项目)
Tiptap 基于 ProseMirror,天然支持 reactive state,更适合 Vue 3 的 Composition API 风格:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 使用
useEditorHook 创建编辑器,传入content和onUpdate回调; -
onUpdate内直接读取editor.getText().length(自动去标签、保留换行); - 结合
watch监听字数 ref,超限时调用editor.chain().focus().deleteRange({ from: limit, to: editor.state.doc.content.size }).run()精准截断; - 若需禁止粘贴超长内容,可监听
editor.on('paste', ...)并提前校验剪贴板文本长度。
通用拦截策略:不只是“显示红字”
真正响应式的拦截,要覆盖用户所有输入路径(键盘、粘贴、拖入、undo/redo):
-
粘贴拦截:监听
paste事件,用event.clipboardData?.getData('text/plain')获取纯文本预判长度,超限则event.preventDefault(); -
输入拦截:对原生
input或编辑器内部 keydown,判断当前光标位置 + 新增字符后是否超限,是则阻止默认行为; -
服务端兜底:前端限制可被绕过,提交时仍需后端校验并返回明确错误(如
400 字数超限:当前 3021 字,上限 3000 字); - 视觉反馈分级:未超限时灰色显示 “2850 / 3000”;剩余 ≤100 字变橙色;超限立即变红色 + 工具栏置灰 + 输入框失焦。
避坑要点:字符计数的真实含义
别直接用 string.length —— 它对中文、emoji、全角符号不友好:
- 中文标点(,。!?)、中文字符、日韩文字均占 1 个 JS 字符位,没问题;
- 但部分 emoji(如 ??、??)由多个 Unicode 码点组成,
.length会高估; - 若后端数据库用 UTF-8 字节限制(如 MySQL
VARCHAR(2000)),需用new TextEncoder().encode(str).length计算真实字节数; - 业务明确要求“汉字+字母+数字共 XXX 字”,就严格用正则
str.match(/[\u4e00-\u9fa5a-zA-Z0-9]/g)?.length || 0。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










