在工作中我们经常要用到富文本编辑器 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>
最后效果如下