我开源了一个 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 二次开发
  • 编辑器工程
  • 低代码平台
  • 前端工程化

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


相关推荐
安且惜2 小时前
带弹窗的页面--以表格形式展示
前端·javascript·vue.js
摘星编程3 小时前
用React Native开发OpenHarmony应用:NFC读取标签数据
javascript·react native·react.js
GISer_Jing3 小时前
AI驱动营销:业务技术栈实战(From AIGC,待总结)
前端·人工智能·aigc·reactjs
GIS之路5 小时前
GDAL 实现影像裁剪
前端·python·arcgis·信息可视化
AGMTI5 小时前
webSock动态注册消息回调函数功能实现
开发语言·前端·javascript
不会Android的潘潘5 小时前
受限系统环境下的 WebView 能力演进:车载平台 Web 渲染异常的根因分析与优化实践
android·java·前端·aosp
建军啊5 小时前
java web常见lou洞
android·java·前端
阳无5 小时前
宝塔部署的前后端项目从IP访问改成自定义域名访问
java·前端·部署
Galloping-Vijay5 小时前
解决 WSL2 + Windows Hosts + 开启 VPN 后无法访问本地 Web 服务的问题
前端·windows