如何开发Mind Elixir插件:从install安装机制到自定义功能的完整指南
【免费下载链接】mind-elixir-core⚗ Mind Elixir 是一个框架无关的前端思维导图内核项目地址: https://gitcode.com/SSShooter/mind-elixir-core
本文带你一步步学会开发Mind Elixir 插件:先搞懂install安装机制的底层原理,再结合事件总线与实例方法,从零写出一个自定义功能完整的思维导图插件。Mind Elixir 是一个框架无关的前端思维导图内核,插件是扩展它最优雅的方式。
为什么Mind Elixir适合二次开发
在写插件之前,先了解它能扩展什么:
| 能力 | 说明 |
|---|---|
| 🎯 实例方法 | getData()、refresh()、layout()等百余种方法对插件开放 |
| 📡 事件总线 | 节点增删改、缩放、选中等操作都会派发事件 |
| 🧩 内置插件参考 | 撤销/重做、右键菜单、工具栏本身就是插件 |
| 🧹 清理机制 | 实例销毁时自动执行注册的清理函数 |
也就是说:内置功能 = 插件 + 实例方法,你写自定义插件的套路和官方一模一样。
安装机制剖析:install到底做了什么
很多教程只说"调用mind.install(plugin)即可安装插件",但它的实现其实只有两行,位于 src/interact.ts:
install = function (this, plugin) { plugin(this) // 把实例 this 交给插件函数 }这就是 Mind Elixir 插件的全部安装机制:
插件就是一个普通函数,参数是思维导图实例(MindElixirInstance)。
// 最小插件 function myPlugin(mei) { console.log(mei.getData()) // 立即可用:拿到全部节点数据 } mind.install(myPlugin)没有注册表、没有生命周期钩子、没有依赖注入——简单到极致,也因此没有任何学习门槛。插件能做的一切,都来自它拿到的mei实例。
插件开发的三大核心构件
构件一:实例方法(Instance Methods)
实例上挂载了所有核心能力,插件内直接调用即可:
function myPlugin(mei) { const data = mei.getData() // 读取节点数据 mei.refresh(data) // 修改数据后重绘 mei.scale(1.2) // 缩放 mei.toCenter() // 回到中心 mei.bus // 事件总线(见下) }方法清单可在 src/methods.ts 和 src/index.ts 中查阅。
构件二:事件总线(Bus)
Mind Elixir 内部基于发布-订阅模型派发事件,实现在 src/utils/pubsub.ts。插件只要addListener就能监听用户操作:
function myPlugin(mei) { // 监听节点操作(增删改都会触发) mei.bus.addListener('operation', op => { console.log(op.name) // addChild | removeNode | finishEdit | moveNodeIn ... }) // 监听选中变化 mei.bus.addListener('selectNodes', nodes => { console.log('当前选中', nodes.length, '个节点') }) }常用事件名(完整定义见 src/utils/pubsub.ts):
| 事件 | 触发时机 | 回调参数 |
|---|---|---|
operation | 节点/连线/概要的任何操作 | { name, obj } |
selectNodes/unselectNodes | 选中/取消选中 | 节点对象数组 |
selectNewNode | 新建节点 | 节点对象 |
expandNode | 展开/折叠节点 | 节点对象 |
changeDirection | 切换布局方向 | 方向值 |
scale/move | 缩放 / 平移 | 缩放值 / 位移 |
showContextMenu | 右键菜单显示 | 鼠标事件 |
构件三:清理机制(Disposable)
实例销毁时会遍历执行this.disposable数组中的清理函数(见 src/methods.ts)。插件注册了全局事件监听时,务必返回清理函数,避免内存泄漏:
function myPlugin(mei) { const onKey = e => { /* ... */ } document.addEventListener('keydown', onKey) return () => { // 实例销毁时自动执行 document.removeEventListener('keydown', onKey) } }注意:官方内置插件(如撤销重做)通过mei.disposable.push(清理函数)注册,而install的返回值不会自动入栈——如果你通过install安装插件,记得自己管理清理时机。
实战一:读懂官方"撤销重做"插件
打开 src/plugin/operationHistory.ts,你会发现它的骨架正是上面三大构件的完整示范:
- 监听事件:
mei.bus.addListener('operation', handleOperation),每次操作记录一份数据快照; - 注入方法:直接给实例挂上
mei.undo/mei.redo/mei.clearHistory,之后任何代码(包括你的插件)都能调用; - 返回清理函数:注销事件监听、移除键盘监听。
它还在init阶段被自动挂载(见 src/methods.ts),说明"官方插件"与你"自定义插件"的唯一区别,只是挂载的时机。
实战二:写一个"自动保存"插件
综合三大构件,下面是一个真实场景的插件:每次节点变更 500ms 后,把数据 POST 到后端。
// savePlugin.js export default function savePlugin(mei) { let timer const save = () => { // 通过实例方法导出数据,无需触碰内部结构 fetch('/api/mindmap', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(mei.getData()), }) } const onOperation = () => { clearTimeout(timer) timer = setTimeout(save, 500) // 防抖 } mei.bus.addListener('operation', onOperation) return () => { // 清理函数 mei.bus.removeListener('operation', onOperation) clearTimeout(timer) } }// 使用 import savePlugin from './savePlugin' mind.install(savePlugin)不到 15 行,一个"数据自动同步"功能就完成了——这就是 Mind Elixir 插件体系的魅力:事件流 + 实例方法 + 清理函数。
进阶技巧:在init之前就装好插件
install在init之前调用也能工作,因为插件拿到的实例已经具备完整的bus与方法挂载(构造函数见 src/index.ts)。但有些能力(如getData的完整数据)要在init(data)之后才可用,因此推荐:
- 先
new MindElixir(options)创建实例; - 再
mind.install(插件); - 最后
mind.init(data)渲染。
初始化时的插件挂载顺序可参考 src/methods.ts:工具栏 → 键盘 → 选中 → 拖拽 → 右键菜单 → 撤销重做。
常见问题速查
Q:插件能访问节点数据吗?能。mei.getData()返回完整数据对象;单个节点可用mei.findEle(nodeId).nodeObj获取。
Q:多个插件互相干扰吗?不会。每个插件只持有自己的闭包状态,通过事件总线解耦,天然支持组合。
Q:想监听用户操作来统计使用量?监听operation事件,op.name即操作类型,op.obj是目标节点。
总结
| 步骤 | 要点 |
|---|---|
| 1️⃣ 理解机制 | install=plugin(this),插件就是一个接收实例的函数 |
| 2️⃣ 订阅事件 | 用mei.bus.addListener监听操作流 |
| 3️⃣ 调用方法 | getData/refresh/scale等覆盖 90% 需求 |
| 4️⃣ 注册清理 | 返回清理函数,保持内存干净 |
| 5️⃣ 参考官方 | src/plugin/ 下每个文件都是模板 |
掌握install安装机制后你会发现:Mind Elixir 插件开发没有魔法,一切能力都挂在实例上,一切变化都流经事件总线。去读一遍官方内置插件,然后动手写你的第一个插件吧!
【免费下载链接】mind-elixir-core⚗ Mind Elixir 是一个框架无关的前端思维导图内核项目地址: https://gitcode.com/SSShooter/mind-elixir-core
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考