wangeditor自定义菜单

3,219 阅读1分钟

在工作中我们经常要用到富文本编辑器 wangeditor 就很不错,有详细的中文文档 官网

但是使用的时候不能满足我们的使用,需要自定义菜单,找了一圈没看到怎么去解决,最后找到了解决方案,这里记录一下:

我们省略前面的安装,一级组件的引入

这里需要创建一个自定义菜单类


import { Boot } from '@wangeditor/editor'
//自定义菜单
class MyButtonMenu {                       // JS 语法

    constructor(title,iconSvg,tag,exec) {
        this.title = title; // 自定义菜单标题
        this.iconSvg = iconSvg; // 自定义菜单的svg
        this.tag = tag; //自定义菜单的类型
        this.exec = exec //自定义菜单点击的方法
    }

    // 获取菜单执行时的 value ,用不到则返回空 字符串或 false
    getValue(editor) {                              // JS 语法
        return ' hello '
    }

    // 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
    isActive(editor) {                    // JS 语法
        return false
    }

    // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
    isDisabled(editor) {                     // JS 语法
        return false
    }

    // 点击菜单时触发的函数
    // exec(editor, value) {                              // JS 语法
    //     if (this.isDisabled(editor)) return
    //     editor.insertText(value) // value 即 this.value(editor) 的返回值
    // }

}

  
  let {title,iconSvg,tag,exec} = {
   title:,按钮的名称
   iconSvg:"<svg t="1689232587150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2492" width="200" height="200"><path d="M832 760V250.5c0-8.5 3.4-16.6 9.4-22.6L1001 68.3c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L796.1 182.6c-6 6-14.1 9.4-22.6 9.4H264c-4.4 0-8-3.6-8-8V8c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v176c0 4.4-3.6 8-8 8H8c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h176c4.4 0 8 3.6 8 8v504c0 35.3 28.7 64 64 64h504c4.4 0 8 3.6 8 8v176c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V840c0-4.4 3.6-8 8-8h176c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H840c-4.4 0-8-3.6-8-8zM264 256h439.4c7.1 0 10.7 8.6 5.7 13.7L269.7 709.1c-5 5-13.7 1.5-13.7-5.7V264c0-4.4 3.6-8 8-8z m496 512H320.6c-7.1 0-10.7-8.6-5.7-13.7l439.4-439.4c5-5 13.7-1.5 13.7 5.7V760c0 4.4-3.6 8-8 8z" p-id="2493"></path></svg>",//按钮的svg图标
        tag:"button",//按钮类型
        exec(){
            //点击后执行的方法
        }
}

  // 我们在组件还没创建之前去初始化菜单,一定要在组件还没初始化前创建
    const menu1Conf = {
        key: 'tailorImage', // 定义 menu key :要保证唯一、不重复(重要)
        factory() {
          return new MyButtonMenu(title,iconSvg,tag,exec) // 把 `MyButtonMenu` 替换为你菜单的 class
        },
      }
    Boot.registerMenu(menu1Conf)

然后我们要在使用的地方去引入刚刚导出的函数

<template>
    <div style="padding: 0 150px;">
        <Toolbar
            :editor="editor"
            :defaultConfig="toolbarConfig"
            :mode="mode"
        />
        <!-- 在Toolbar和Editor组件之间的组件会自定嵌入到富文本的内容和工具栏之间 -->
        <el-input 
            class="edit-input edit-input-title top-margin"  
            maxlength="20" 
            show-word-limit 
            v-model="fileNmae" 
            placeholder="请输入文件名" 
            clearable
        ></el-input>
        <el-input 
            class="edit-input edit-input-des" 
            maxlength="50" 
            show-word-limit
            v-model="fileDescription" 
            placeholder="请输入文件描述" 
            clearable
        ></el-input>
        <Editor
            style="height: 500px; overflow-y: hidden;"
            v-model="html"
            :defaultConfig="editorConfig"
            :mode="mode"
            class="deit-box"
            @onCreated="onCreated"
        />
    </div>
</template>
<script>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { DomEditor } from '@wangeditor/editor'

export default {
    components: { Editor, Toolbar,cropperDlg },
    data() {
        return {
            fileNmae:"",
            fileDescription:"",

            editor: null,
            html: ``,
            toolbarConfig: { },
            editorConfig: { placeholder: '请输入内容 .  .  .' },
            mode: 'default', // or 'simple'


            // 防止重复提交
            loading: false,
        }
    },
    methods: {
        aaa(){
            console.log(this.html)
        },
        onCreated(editor) {
            this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
            
           this.$nextTick(()=>{
                const toolbar = DomEditor.getToolbar(this.editor)
                const curToolbarConfig = toolbar.getConfig()
                curToolbarConfig.customInsert = this.insertImg,
                //可以通过curToolbarConfig.toolbarKeys来拿到所有的菜单,也可以直接修改
                curToolbarConfig.toolbarKeys = [
                    // 菜单 key
                    "blockquote", 
                    // 分割线
                    "|",
                    // 菜单 key
                    "bold","underline","italic",
                    // 菜单组,包含多个菜单
                    {   
                        key: 'group-more-style',// 必填,要以 group 开头
                        title: '更多',  // 必填
                        iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path></svg>', // 可选
                        menuKeys: ['through', 'code', 'sup', 'sub', 'clearStyle']// 下级菜单 key ,必填
                    }, 
                    "color","bgColor","|",
                    "fontSize","fontFamily","lineHeight",
                    "|",
                    "bulletedList","numberedList","todo",
                    {
                        key: 'group-justify', 
                        title: '对齐', 
                        iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>',
                        menuKeys: ['justifyLeft', 'justifyRight', 'justifyCenter', 'justifyJustify']
                    },
                    {
                        key: 'group-indent', 
                        title: '缩进', 
                        iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>', 
                        menuKeys: ['indent', 'delIndent']
                    },
                    "|",
                    "emotion","insertLink",
                    "uploadImage",
                   
                    "insertTable","codeBlock","divider",
                    "|",
                    "undo","redo",
                    "|",
                    "fullScreen",
                   
                ]



                //修改悬浮控件
                let imgMenuKeys = editor.getConfig().hoverbarKeys.image.menuKeys
                imgMenuKeys.push("tailorImage")
                console.log(this.editor) 
                // imgMenuKeys.splice(imgMenuKeys.indexOf("editImage"),1)
                let editorConfig = editor.getConfig()


                let uploadImageConfig = this.editor.getMenuConfig('uploadImage') 
                uploadImageConfig.fieldName = "file"
                uploadImageConfig.server = "http://info.menganl.cn/api/uploadd"
                //实现自定义上传
                uploadImageConfig.customUpload = (file, insertFn)=>{
                    // file 即选中的文件
                    // 自己实现上传,并得到图片 url alt href
                    // 最后插入图片
                    this.blobToDataURI(file,(data)=>{
                        insertFn(data, file.name, data)
                        this.insertFn = insertFn
                        this.files.push({file,url:data})
                    })
                }
                uploadImageConfig.onBeforeUpload = function(data){
                    console.log(data)
                }
                uploadImageConfig.onSuccess = function(data){
                    console.log(data)
                }
           })
          
        },
 
        
       
    },
    created(){
      
    },
    mounted() {
       
    },
    beforeDestroy() {
        const editor = this.editor
        if (editor == null) return
        editor.destroy() // 组件销毁时,及时销毁编辑器
    }
}
</script>
<style lang="less" scoped>
.edit-input/deep/ .el-input__inner {
    border: 0;
  }
  /* 如果你的 el-input type 设置成textarea ,就要用这个了 */
  .edit-input /deep/ .el-textarea__inner {
    border: 0;
    resize: none;/* 这个是去掉 textarea 下面拉伸的那个标志,如下图 */
  }
  .edit-input-title{
    height: 50px;
    &/deep/ .el-input__inner{
        height: 50px;
    }
  }
  .top-margin{
    margin-top: 20px;
  }
  .edit-input {
    margin-bottom: 20px;
  }
  .deit-box{
    /deep/#w-e-textarea-1{
        padding: 0 100px;
    }
    /deep/.w-e-text-placeholder{
        padding-left: 100px;
    }
  }
</style>

最后效果如下

image.png