我开源了一个 GrapesJS 插件

一、背景:为什么要做这个插件?

在做可视化编辑器(证书编辑器、模板编辑器、低代码页面编辑器)时,我大量使用了 GrapesJS

但在真实业务中,很快遇到了一个非常实际的问题:

Canvas 内的文本输入监听并不可靠

具体表现包括:

  • 中文输入法(IME)下:

    • input 事件触发不稳定
    • composition 阶段无法准确感知文本变化
  • GrapesJS 的 Canvas 是 iframe:

    • iframe reload 后监听全部失效
    • DOM 动态变化时无法自动重新绑定
  • 高频输入会导致:

    • 性能抖动
    • 无法做实时联动(预览、校验、联想)

而业务侧的诉求非常明确:

✅ 希望能稳定捕获:

  • 用户正在输入的文本(实时)
  • 用户完成输入的文本(提交)
  • 支持中文 / 日文 / 韩文输入法
  • 可配置节流

这就是 grapesjs-text-change 诞生的背景。


二、插件目标与能力设计

插件目标非常清晰:

🎯 为 GrapesJS 提供稳定、工程化的文本输入监听能力

核心能力:

能力 说明
✅ IME 兼容 支持中文 / 日文输入
✅ iframe 自动重绑定 Canvas reload 后自动恢复
✅ 输入节流 避免高频触发
✅ 标准事件输出 对外统一事件接口
✅ TypeScript 支持 类型安全
✅ 即插即用 零侵入集成

三、使用效果展示

安装:

bash 复制代码
npm install grapesjs-text-change

集成:

ts 复制代码
import TextChangePlugin from 'grapesjs-text-change';

editor.use(TextChangePlugin, {
  throttle: 200,
});

editor.on('text:input', e => {
  console.log('实时输入:', e.text);
});

editor.on('text:commit', e => {
  console.log('输入完成:', e.text);
});

你可以:

  • 实时联动右侧预览
  • 做文本校验
  • 同步外部状态
  • 做多语言编辑联动

四、核心实现思路

1️⃣ iframe 自动绑定机制

GrapesJS 的 Canvas 是 iframe,不能只绑定一次。

插件内部监听:

ts 复制代码
editor.on('canvas:ready', bindFrame);
editor.on('canvas:frame:load', bindFrame);

每次 iframe 重建时:

  • 重新获取 contentDocument
  • 扫描 [contenteditable]
  • 自动绑定监听器

确保不会因为刷新导致监听失效。


2️⃣ IME 输入兼容处理

中文输入并不是简单的 input 事件。

需要监听:

  • compositionstart
  • compositionupdate
  • compositionend
  • input

插件内部维护一个状态机:

ts 复制代码
let composing = false;

el.addEventListener('compositionstart', () => composing = true);
el.addEventListener('compositionend', () => {
  composing = false;
  emitCommit();
});

el.addEventListener('input', () => {
  if (!composing) emitInput();
});

这样可以:

  • 避免拼音阶段误触发
  • 只在真正提交时触发 commit

3️⃣ 输入节流(Throttle)

高频输入如果不做节流:

  • 会触发大量业务逻辑
  • 性能下降明显

插件内使用可配置 throttle:

ts 复制代码
emitInput = throttle(fn, options.throttle);

用户可根据业务自由配置:

ts 复制代码
{ throttle: 100 }

4️⃣ 标准事件设计

插件对外只暴露两个稳定事件:

ts 复制代码
text:input   // 实时输入
text:commit  // 输入完成

统一事件格式:

ts 复制代码
{
  text: string;
  target: HTMLElement;
}

避免业务侧直接耦合 DOM。


五、工程化构建

📦 技术栈

  • TypeScript
  • tsup(打包)
  • ESM + CJS 双产物
  • 自动生成 d.ts

⚙️ tsup 配置示例

ts 复制代码
export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm', 'cjs'],
  dts: true,
  sourcemap: true,
  clean: true,
});

打包:

bash 复制代码
pnpm build

📁 项目结构

复制代码
grapesjs-text-change/
├── .github/
│   └── workflows/
│       ├── release.yml      # npm 发布 workflow
│       └── pages.yml        # GitHub Pages 部署 workflow
├── demo/                    # 在线演示
│   ├── index.html
│   ├── main.ts
│   ├── vite.config.ts
│   └── package.json
├── src/
│   ├── TextChangePlugin.ts  # 核心插件逻辑
│   └── index.ts             # 入口文件
├── package.json
├── tsup.config.ts
├── tsconfig.json
├── .gitignore
└── README.md

保持:

  • 职责拆分清晰
  • 可测试
  • 可扩展

六、自动化发布

通过 GitHub Actions + Changeset:

  • 自动版本管理
  • 自动发布到 npm
  • 自动生成 changelog

这保证了:

✅ 插件可持续维护

✅ 发布过程稳定可靠

✅ 降低人工成本


七、适合哪些场景?

这个插件特别适合:

✅ 可视化编辑器

✅ 富文本编辑

✅ 模板编辑器

✅ 多语言编辑

✅ 低代码平台

✅ 在线证书 / 海报设计器

如果你在 GrapesJS 中:

  • 需要稳定监听文本变化
  • 需要支持中文输入
  • 不想重复踩坑

可以直接使用这个插件。


八、开源地址

欢迎 Star ⭐ / Issue / PR:

👉 GitHub
https://github.com/xiayuguo/grapesjs-text-change

👉 NPM
https://www.npmjs.com/package/grapesjs-text-change


九、结语

这个插件本质上是:

一次真实业务驱动的工程化抽象实践。

如果你也在做:

  • GrapesJS 二次开发
  • 编辑器工程
  • 低代码平台
  • 前端工程化

欢迎交流经验,一起打磨更好的工具生态 🚀


相关推荐
旺仔Sec7 小时前
一文带你看懂免费开源 WAF 天花板!雷池 (SafeLine) 部署与实战全解析
web安全·网络安全·开源·waf
心疼你的一切7 小时前
语音革命:CANN驱动实时语音合成的技术突破
数据仓库·开源·aigc·cann
hedley(●'◡'●)7 小时前
基于cesium和vue的大疆司空模仿程序
前端·javascript·vue.js·python·typescript·无人机
qq5_8115175157 小时前
web城乡居民基本医疗信息管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
百思可瑞教育7 小时前
构建自己的Vue UI组件库:从设计到发布
前端·javascript·vue.js·ui·百思可瑞教育·北京百思教育
百锦再7 小时前
Vue高阶知识:利用 defineModel 特性开发搜索组件组合
前端·vue.js·学习·flutter·typescript·前端框架
开源能源管理系统7 小时前
MyEMS开源能源管理系统:赋能废旧金属回收加工行业绿色转型与降本增效
开源·能源·能源管理系统·零碳工厂
CappuccinoRose8 小时前
JavaScript 学习文档(二)
前端·javascript·学习·数据类型·运算符·箭头函数·变量声明
廖松洋(Alina)8 小时前
【收尾以及复盘】flutter开发鸿蒙APP之成就徽章页面
flutter·华为·开源·harmonyos·鸿蒙
这儿有一堆花8 小时前
Vue 是什么:一套为「真实业务」而生的前端框架
前端·vue.js·前端框架