wangEditor动态调用多个编辑器并自定义工具栏

const editorConfig = {
    placeholder: '输入内容',
    onChange(editor) {
        var html = editor.getHtml();
        html = util.removeSpace(html);//去空格及<br>
        //document.getElementById("content").value = html //这里是固定ID,不方便使用
    },
    MENU_CONF: {
        uploadImage: {
            fieldName: "file",
            server: "/uploads.html",
            // 单个文件的最大体积限制,默认为 2M
            maxFileSize: 1 * 1024 * 1024, // 1M

            // 最多可上传几个文件,默认为 100
            maxNumberOfFiles: 10,

            allowedFileTypes: ["image/*"],
            // 超时时间,默认为 10 秒
            timeout: 30 * 1000, // 5 秒
            // 单个文件上传成功之后
            onSuccess(file, res) {          // JS 语法
                console.log(`${file.name} 上传成功`, res);
                if (res.code != 0) {
                    alert(res.error)
                }
            },

            // 单个文件上传失败
            onFailed(file, res) {           // JS 语法
                console.log(`${file.name} 上传失败`, res)
            },

            // 上传错误,或者触发 timeout 超时
            onError(file, err, res) {               // JS 语法
                console.log(`${file.name} 上传出错`, err, res)
            },
            customInsert(res, insertFn) {                  // JS 语法
                // res 即服务端的返回结果
                console.log(res, insertFn)
                // 从 res 中找到 url alt href ,然后插入图片
                insertFn(res.url)
            },
        },
        uploadVideo: {
            fieldName: "file",
            server: "/uploads.html",
            // 单个文件的最大体积限制,默认为 2M
            maxFileSize: 10 * 1024 * 1024 * 1024, // 1M

            // 最多可上传几个文件,默认为 100
            maxNumberOfFiles: 100,

            allowedFileTypes: ["video/*"],
            // 超时时间,默认为 10 秒
            timeout: 60 * 1000, // 5 秒
            // 单个文件上传成功之后
            //onSuccess(file: File, res: any) {  // TS 语法
            onSuccess(file, res) {          // JS 语法
                console.log(`${file.name} 上传成功`, res)
                if (res.code != 0) {
                    alert(res.error)
                }
            },

            // 单个文件上传失败
            //onFailed(file: File, res: any) {   // TS 语法
            onFailed(file, res) {           // JS 语法
                console.log(`${file.name} 上传失败`, res)
            },

            // 上传错误,或者触发 timeout 超时
            onError(file, err, res) {               // JS 语法
                console.log(`${file.name} 上传出错`, err, res)
            },
            customInsert(res, insertFn) {                  // JS 语法
                // res 即服务端的返回结果
                console.log(res, insertFn)
                // 从 res 中找到 url alt href ,然后插入图片
                insertFn(res.url)
            },
        },
    },
};

//=================添加自定义菜单开始======================
//源码
class MyMenuBody {
    constructor() {
        this.title = "源码";
        this.tag = "button";
        this.sourceActive = false
    }
    getValue(editor) {
        if (this.sourceActive) {
            return editor.getText()
        } else {
            return editor.getHtml()
        }
    }
    isActive(editor) {
        return this.sourceActive
    }
    isDisabled(editor) {
        return false // or true
    }
    exec(editor, value) {
        this.sourceActive = !this.sourceActive;
        editor.clear();
        wangEditor.SlateTransforms.setNodes(editor, { type: "paragraph" }, { mode: "highest"});
        value = util.removeSpace(value);//去空格及<br>
        if (this.isActive()) {
            editor.insertText(value)
        } else {
            editor.dangerouslyInsertHtml(value)
        }
    }
}
const myMenuConfBody = {
    key: "html",
    factory() {
        return new MyMenuBody()
    }
};
wangEditor.Boot.registerMenu(myMenuConfBody);

//客服
class MyMenuService {
    constructor() {
        this.title = "客服";
        this.tag = "button";
        this.showDropPanel = true
    }
    isActive(editor) {
        return false
    }
    getValue(editor) {
        return ''
    }
    isDisabled(editor) {
        return false
    }
    exec(editor, value) {

    }
    // 定义 DropPanel 内部的 DOM Element
    getPanelContentElem(editor) {
        const $list = $(`<ul class="w-e-panel-my-list">
                <li>客服名称</li><li>客服电话</li><li>客服微信</li><li>客服二维码</li><li>客服性别</li>
                </ul>`);

        $list.on('click', 'li', function () {
            var txt = $(this).text()
            if (txt === '客服名称') {
                editor.insertText('{客服名称}')
            } else if (txt === '客服电话') {
                editor.insertText('{客服电话}')
            } else if (txt === '客服微信') {
                editor.insertText('{客服微信}')
            } else if (txt === '客服二维码') {
                editor.insertText('{客服二维码}')
            } else if (txt === '客服性别') {
                editor.insertText('{客服性别}')
            }
        });
        return $list[0] // 返回 DOM Element 类型
    }
}

const myMenuConfService = {
    key: "service",
    factory() {
        return new MyMenuService()
    }
};

wangEditor.Boot.registerMenu(myMenuConfService);//===========注册自定义菜单===================

const toolbarConfig = {
    insertKeys: {
        index: 0,
        keys: ["html","service"],//===========插入自定义菜单===================
    }
};
//=================添加自定义菜单结束======================


/**
 * html页面
 * <div class="layui-input-block">
 <textarea id="{$v.field}" name="{$v.field}" class="layui-textarea layui-hide">{$vo[$v['field']]??''}</textarea>
 <div id="editor—{$v.field}" style="border: 1px solid #f0f0f0">
 <div id="toolbar-{$v.field}" style="border-bottom: 1px solid #f0f0f0"><!-- 工具栏 --></div>
 <div id="editor-{$v.field}" style="height: 350px"><!-- 编辑器 --></div>
 </div>
 </div>
 //这里是调用
 <script>
 createE('{$v.field}',"{$vo[$v['field']]??''}",'','html');
 </script>

 * @param field
 * @param body
 * @param url 上传文件服务器地址
 * @param key 自定义菜单'html,service',默人为'',多个用英文逗号隔开
 * @param pos 自定义菜单插入位置,默人为0,起始位置
 */

//创建编辑器,以供页面调用
function createE(field,body,url,key,pos) {
    key = key || ''; pos = pos || 0;
    var keys = key?key.split(','):[],E = {};

    E['editorConfig_'+field] = editorConfig;
    if(url){
        E['editorConfig_'+field].MENU_CONF.uploadImage.server = url;
        E['editorConfig_'+field].MENU_CONF.uploadVideo.server = url;
    }
    E['editorConfig_'+field].onChange = function (editor) {
        var html = editor.getHtml();
        html = util.removeSpace(html);//去空格及<br>
        document.getElementById(field).value = html //textarea的ID
    };
    E['editor_'+field] = wangEditor.createEditor({
        selector: '#editor-'+field,
        html: '<p><br></p>',
        config: E['editorConfig_'+field],
    });
    toolbarConfig.insertKeys = {index: pos,keys: keys};
    var editor = E['editor_'+field];
    wangEditor.createToolbar({
        editor,
        selector: '#toolbar-'+field,
        config: toolbarConfig,
    });
    //editor.setHtml(util.unescape(body));//反编码
    editor.setHtml(body);
}

将以上代码保存为config.js,引入即可调用,改其它配置:修改对应配置项,或增加配置项。