从 wangEditor 迁到 wangEditor-next
背景原版 wangEditor 已经很久不维护了对中文输入法IME组合输入的支持有历史遗留问题。具体表现为当输入的候选拼音占位字符和最终确定的汉字在文本节点里没有正确合并时内容就没有即时渲染直到下一次编辑动作回车/删除触发了重渲染汉字才迟到地显示出来。为解决对应问题将其迁移到wangEditor-next版本。从 wangEditor 迁到 wangEditor-next先解决输入法老毛病又踩了工具栏按钮集体置灰的坑修复一个 bug 时发现比较容易的竟然是那个看起来更吓人的输入法问题。最近给项目里的文本编辑器做了一次大迁移从原版wangEditor升级到社区维护的wangeditor-next/editor。本来只是想修一个中文输入法的老毛病结果迁移完成、输入法问题解决后又冒出来一个更隐蔽的工具栏 bug。两个问题都值得记录这一篇把完整过程写下来。一、起因原版 wangEditor 的输入法老毛病一开始项目用的是原版wangeditor/editor一直存在一个很烦人的中文输入法 bug在行首输入中文不显示要敲回车或删除后才突然冒出来。这个毛病的根源在于原版 wangEditor 已经很久不维护了对中文输入法IME组合输入的支持有历史遗留问题。具体表现为当输入的候选拼音占位字符和最终确定的汉字在文本节点里没有正确合并时内容就没有即时渲染直到下一次编辑动作回车/删除触发了重渲染汉字才迟到地显示出来。这个问题在输入框类组件里属于能忍但很难受的那种尤其对中文用户几乎是天天都要撞上。原版不再更新靠打补丁治标不治本于是我们把目光投向社区维护的分支——wangeditor-next/editor。维护者明确确认这个 IME 问题在新版本里已经修复。二、迁移换包名API 几乎不动wangeditor-next是原版 wangEditor 的社区分支API 设计基本一致迁移比想象中顺利包名wangeditor/editor→wangeditor-next/editorVue 封装wangeditor/editor-for-vue→wangeditor-next/editor-for-vue版本对齐editor和editor-for-vue都锁定到6.4.2代码改动改import来源把样式引入路径从wangeditor/editor/dist/css/style.css换成wangeditor-next/editor/dist/css/style.css组件用法Editor、Toolbar、createEditor/createToolbar等 API 完全兼容toolbarConfig、editorConfig、事件回调都照旧迁移完成后验证果然——行首中文输入不显示的问题解决了。正当我以为收工时紧接测试发现了一个新的工具栏问题。三、新坑工具栏按钮集体置灰、右键却正常问题迁移后工具栏上的有序列表 / 无序列表 / 待办 / 表情按钮置灰、点不了但右键悬浮菜单里的无序列表却能用。现象可以拆成三条看起来互相矛盾的关键线索有序列表numberedList、无序列表bulletedList、待办todo、表情emotion工具栏上置灰。加粗bold、颜色color等同批控件看起来正常。右键菜单里的无序列表能用。第一反应当然是这几个按钮的模块没注册。因为 wangEditor 的机制是一个菜单按钮 一个注册在key下的菜单工厂工具栏渲染时找不到工厂就渲染不出来。但「加粗能用、列表不能用、右键能用」这三条摆在一起立刻否掉了模块完全没注册的猜测——它们很多都在同一个模块basic-modules里。如果是注册问题加粗也该一起挂掉。于是转向怀疑是不是这四个按钮的isDisabled判断逻辑在迁移后出错四、一度跑偏盯着 isDisabled 猜了很久wangEditor 里每个菜单都有isDisabled(editor)返回 true 就置灰。列表/待办类的逻辑通常是这样isDisabled(editor){// 选中块为空、或光标在 void/pre/code/table 节点里 → 禁用return!selection||getTopLevelSelectedBlocks(editor).length0||...;}我一度把注意力全放在为什么bold的isDisabled返回 false、而bulletedList返回 true上怀疑迁移后光标选择selection状态没正常建立。这方向也走了挺深但始终说服不了自己——它们的底层判断逻辑几乎一样没理由加粗能拿到正常 selection、列表就拿不到。就在纠结 selection 的时候用户贴了一条控制台报错直接把方向拉了回来。五、控制台报错才是根子Uncaught (in promise) Error: Not found menu item factory by key link注意报错的 key 是link而不是列表/待办/表情里的任何一个。但正是这个看起来不相关的 key把所有按钮一起打趴下了。顺着这条报错我去node_modules/wangeditor-next/editor的分发包dist/index.mjs打包产物里一查发现了迁移时最容易被忽略的坑wangEditor-next 悄悄改了一堆菜单 key我在打包产物里逐个搜索key:xxx这种菜单工厂注册声明把白名单里的 key 全过了一遍发现有三个 key 在原版里存在、在 next 里根本不存在白名单里写的 key结果正确的 keylink❌ 无此工厂insertLinkimage图片组内❌ 无此工厂insertImagetable❌ 无此工厂insertTable为什么一个坏 key 会让一堆好按钮置灰这是整个问题最核心、也最反直觉的地方。wangEditor-next 的Toolbar拿到toolbarKeys后会逐个把 key 解析成已注册的菜单工厂。只要中间遇到一个哪怕一个解析不了的 key就会抛出Not found menu item factory by key ...。关键在(in promise)这几个字这个错误是在工具栏的异步/响应式构建过程中抛出的。一旦抛错工具栏的初始化流程就被打断——本该继续往下算的那些按钮的可用状态disabled/active全部停在默认的灰那儿更新不出来。所以白名单里那几个无效 keylink、image、table就像三颗老鼠屎坏了一锅汤自己抛错不说还把bulletedList、numberedList、todo、emotion这些本来完全正常的按钮一起拖进灰色状态。为什么右键/悬浮菜单却一直正常这正好解释了那条看似矛盾的现象工具栏走toolbarKeys→ 解析成工厂这套先校验、会抛错的逻辑。坏 key 一来整个工具栏初始化被打断。悬浮/右键菜单hoverbar根本不经过toolbarKeys这套校验而是在选中内容时动态弹出。菜单工厂和插件都是好的所以一直能用。也就是说问题从来不是列表/待办/表情这三个按钮坏了而是工具栏因为别的坏 key 崩了把他们都拖下水了。六、修复把无效 key 全部改掉直接在白名单里把三个无效 key 改成有效 key 即可一行都没多动// frontend/src/components/RichEditor.vuefunctionbuildToolbarKeys():IToolbarConfig[toolbarKeys]{return[headerSelect,blockquote,bold,underline,italic,through,color,bgColor,clearStyle,fontFamily,fontSize,bulletedList,numberedList,todo,emotion,insertLink,// 原先是 link{key:group-image,title:图片,iconSvg:,menuKeys:[insertImage,viewImageLink,deleteImage,editImage],// 原先是 image,...},insertTable,// 原先是 tablecodeBlock,code,divider,undo,redo,]}修完后我把所有白名单 key 在打包产物里逐一核对抗有效性确保不再有漏网的坏 keyheaderSelect OK · blockquote OK · bold OK · ... · bulletedList OK · todo OK emotion OK · insertLink OK · insertImage OK · ... · insertTable OK · ...全部OK。Vite dev 是热更新的用户刷新页面后控制台不再报Not found menu item factory四个按钮恢复可点问题解决。七、复盘两轮踩坑四条经验菜单可用状态和菜单是否注册要先分开。isDisabled返回置灰和工厂根本没注册是两码事。前者靠改逻辑解决后者靠修 key/注册解决。别一上来就怀疑自己的判断逻辑。看控制台报错别看感觉。我盯着为什么加粗能行、列表不行猜了很久一个link的报错就把方向拉回来了。遇到可疑 bug先把运行时异常翻出来。换库后菜单 key 是会变的。wangeditor/editor→wangeditor-next/editor不能只对 API菜单注册的 key 名link→insertLink、image→insertImage、table→insertTable也会改。最稳的核对方式直接去打包产物里搜key:你用的key看能否命中工厂。一个坏 key 会让看起来无关的好按钮一起挂掉。因为工具栏构建是一串整体流程中间抛错会打断后续所有按钮可用状态的更新。所以修的时候要把白名单里所有 key 一次性全查一遍而不是修一个再试一次。附快速核对 wangEditor-next 菜单 key 是否有效遇到类似问题可以在安装目录里快速核对任意 key 是否存在$fnode_modules/wangeditor-next/editor/dist/index.mjs$lineGet-Content$f-Rawforeach($kin (link,insertLink,table,insertTable)){$p$line.IndexOf(key:$k)Write-Output{0,-12} - {1}-f$k,($(if($p-ge0){OK $p}else{INVALID}))}OK表示这个 key 有对应菜单工厂INVALID则表示换成正确的 key通常就是在前面加insert。这次迁移告诉我们修输入法这种看着难的问题往往挺直接而工具栏按钮置灰这种看着简单的问题背后反而藏着坑。别背锅给好按钮先去控制台里找那个抛错的坏 key。