文章目录
- 前言
- Modal插入富文本应用
- 注册新菜单
- 在自定义Modal操作Editor实例
前言
最近在业务中被要求用到了富文本的需求,经过调研最终决定使用国产的 wangeditor ,需要在富文本菜单里插入自己的外部应用,本文旨在记录。
Modal插入富文本应用
参考链接官方issue的一篇帖子: modalMenu方案
注册新菜单
ModalMenu的使用需要在内部定义元素,使代码糅合,业务代码与富文本代码不可分离(参考: 官方文档-自定义拓展功能)
所以使用menu栏上的按钮唤起新弹框,因此要注册个ButtonMenu
定义菜单class
import ReactDOM from "react-dom";
import YourModalMenu from "./YourModalMenu";export default class ModalMenu {id = `modal-${Math.random().toString(36).slice(2)}`;title;tag;$ele;ifInit = false;controlShow;constructor() {this.title = '应用';this.iconSvg = `svg`; // 这里是你自己的svgthis.tag = 'button';this.$ele = document.createElement('div');this.$ele.id = this.id;document.body.appendChild(this.$ele);// super();}getValue(editor) {console.log('getValue--------')return <YourModalMenu onInit={this.modalInit} editor={editor} />}modalInit = (method) => {console.log('modalInit----', method)// 这里把控制react的 方法透出this.controlShow = method;}isActive(editor) {return false // or false}isDisabled(editor) {return false // or true}exec(editor, value) {console.log('exec--------', editor, value, this.ifInit)if (this.ifInit) {this.controlShow(true);return;}ReactDOM.render(value, this.$ele);this.ifInit = true;}
}
- 在react-dom中,通过ReactDOM.render(ele, container)将指定元素(ele)渲染到目标容器(container)上
- 在打开新菜单时,将首先执行getValue(),在此处将editor实例传给自定义的modal;随后在exec()中将自定义的modal渲染到div容器上
新菜单到处并插入到工具栏
// 导出
export const customModalButton = {key: 'customModalButton',factory() {return new ModalMenu()}
}
在主文件里注册
import { Boot, DomEditor } from '@wangeditor/editor'
import { myModalMenuConf } from './customModalButton'Boot.registerMenu(customModalButton)
// 工具栏配置
const toolbarConfig = {insertKeys: {index: -1, // 菜单位置keys: ['customModalButton'], // show menu in toolbar}
}
- 菜单注册时机toolbarConfig需要放在最外层,即主函数之外,否则会报错:
Uncaught (in promise) Error: Duplicated key ‘xxx’ in menu items
。
在自定义Modal操作Editor实例
做一个简单应用:记录光标所在富文本的位置,在此处插入后端返回的应用
const node = {type: 'link', url: 'javascript:void(0);', children: [{ text: AppName, bold: true, clolor: '#eb903a' }]}const iconNode = {type: 'image', src: serviceAppIcon, style: {width: '28px', height: '28px'},children: [{ text: app.AppName, bold: true, clolor: '#eb903a' }]}selectionRef.current && editor.select(selectionRef.current)const nodeList = [iconNode, node ]editor.insertNode(nodeList)
效果