WangEditor5富文本编辑器安装及使用说明——Vue2版本
一、安装
yarn add @wangeditor/editor
# 或者 npm install @wangeditor/editor --save
yarn add @wangeditor/editor-for-vue
# 或者 npm install @wangeditor/editor-for-vue --save二、使用
父组件调用
//使用组件(因为组件销毁不及时,会出现报错Uncaught (in promise) Error: Cannot find a descendant at path,所以使用v-if来让组件和弹出框一起销毁)
<wang-editor v-if="visible" ref="editor" :value.sync="form.content" @updateContent = "updateContent"/>
//引入组件
import WangEditor from '@/components/WangEditor/index.vue';
//获取子组件传回的html
updateContent(val){
this.form.content = val;
},编辑器组件
<template>
<div style="border: 1px solid #ccc">
<!-- 工具栏 -->
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editor"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<!-- 文本输入区域 -->
<Editor
style="height: 500px; overflow-y: hidden"
v-model="html"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="onCreated"
@onChange="onChange"
@onDestroyed="onDestroyed"
@customPaste="customPaste"
/>
</div>
</template>
<script>
import Vue from 'vue';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import { DomEditor } from '@wangeditor/editor';
//图片上传接口
import { UploadBase64 } from '@/api/user/userInfo';
export default Vue.extend({
//注册组件
components: { Editor, Toolbar },
//接受父组件传值
props: {
url: {
//上传图片的url
type: String,
default: ''
},
value: {
//父组件传过来的值
type: String,
default: ''
},
height: {
//编辑器高度,暂时不用
type: Number,
default: 250
}
},
name: 'wang-editor',
data() {
return {
editor: null,
html: this.value,
//工具栏配置区
toolbarConfig: {
//删除表情包,视频上传,代码块组件
excludeKeys: ['emotion', 'group-video',"codeBlock"],
//添加功能
// insertKeys:{
// index:32,
// keys:[{
// 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: ["imageWidth30","imageWidth50","imageWidth100"] // 下级菜单 key ,必填
// }]
// }
},
//编辑器配置区
editorConfig: {
//空白提示
placeholder: '请输入内容...',
//对编辑器功能修改
MENU_CONF: {
//接入图片上传接口
uploadImage: {
customUpload: async (file, insertFn) => {
// JS 语法
const formData = new FormData();
formData.append('file', file);
UploadBase64(formData).then((res) => {
var url = res.data.url;
insertFn(url);
});
}
}
}
},
mode: 'default' // or 'simple'
};
},
watch: {
//监听value,更新编辑器内容
value: function (value) {
this.$nextTick(() => {
this.editor.setHtml(value);
});
}
},
methods: {
//初始化
onCreated(editor) {
this.editor = Object.seal(editor);
},
//输入事件(改一次触发一次)
onChange(editor) {
let value = editor.getHtml();
this.$emit('updateContent', value);
// const list = editor.getAllMenuKeys();
//获取工具栏所有工具的配置(不能放在onCreated中)
// const toolbar = DomEditor.getToolbar(editor);
// const curToolbarConfig = toolbar.getConfig();
// console.log(curToolbarConfig.toolbarKeys); // 当前菜单排序和分组
},
//销毁
onDestroyed(editor) {},
//复制粘贴事件
customPaste(editor, event, callback) {
const html = event.clipboardData.getData('text/html'); // 获取粘贴的 html
// const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
// const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)
// 自定义插入内容
editor.insertText(html);
// 返回 false ,阻止默认粘贴行为
event.preventDefault();
// callback(false) // 返回值(注意,vue 事件的返回值,不能用 return)
// 返回 true ,继续默认的粘贴行为
callback(true);
}
},
mounted() {},
beforeDestroy() {
//销毁事件
const editor = this.editor;
if (editor == null) return;
editor.destroy(); // 组件销毁时,及时销毁编辑器
}
});
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>三、自定义功能
自定义按钮(缩放图片75%)
import { Transforms, Node } from 'slate'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import { Boot ,IButtonMenu, IDomEditor,DomEditor } from '@wangeditor/editor'
class MyButtonMenu { // JS 语法
constructor() {
this.title = '图像' // 自定义菜单标题
this.iconSvg = '<svg t="1698982063081" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1509" width="200" height="200"><path d="M744 62H280c-35.3 0-64 28.7-64 64v768c0 35.3 28.7 64 64 64h464c35.3 0 64-28.7 64-64V126c0-35.3-28.7-64-64-64z m-8 824H288V134h448v752z" p-id="1510"></path><path d="M512 784m-40 0a40 40 0 1 0 80 0 40 40 0 1 0-80 0Z" p-id="1511"></path></svg>' // 可选
this.tag = 'button'
}
// 获取菜单执行时的 value ,用不到则返回空 字符串或 false
getValue(editor) { // JS 语法
return ''
}
// 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
isActive(editor) { // JS 语法
return false
}
getSelectedNode(editor){
return DomEditor.getSelectedNodeByType(editor, 'image')
}
// 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
isDisabled(editor) { // JS 语法
if (editor.selection == null) return true
const imageNode = this.getSelectedNode(editor)
if (imageNode == null) {
// 选区未处于 image node ,则禁用
return true
}
return false
}
// 点击菜单时触发的函数
exec(editor, value) { // JS 语法
if (this.isDisabled(editor)) return
const imageNode = this.getSelectedNode(editor)
if (imageNode == null) return
// 隐藏 hoverbar
const hoverbar = DomEditor.getHoverbar(editor)
if (hoverbar) hoverbar.hideAndClean()
const { style = {} } = imageNode
const props = {
style: {
...style,
width: '75%', // 修改 width
height: '', // 清空 height
},
}
Transforms.setNodes(editor, props, {
match: n => DomEditor.checkNodeType(n, 'image'),
})
}
}
const menu1Conf = {
key: 'image-mobile', // 定义 menu key :要保证唯一、不重复(重要)
factory() {
return new MyButtonMenu() // 把 `YourMenuClass` 替换为你菜单的 class
},
}
Boot.registerMenu(menu1Conf)在image的hoverbar中注册按钮
hoverbarKeys:{
'image': {
// 配置image元素的hoverbar
menuKeys: ["imageWidth30","imageWidth50","imageWidth100","editImage","viewImageLink","deleteImage","image-mobile"],
}
}