wangeditor是一个轻量级富文本编辑器可见网址
创建一个config.js文件:
export default {
menus: [
"head",
"bold",
"fontSize",
// "fontName",
"italic",
"underline",
'|',
"strikeThrough",
"indent",
"lineHeight",
"foreColor",
"backColor",
"link",
'|',
"list",
// "todo",
"image",
"justify",
// "quote",
// "table",
'|',
"code",
"splitLine",
"undo",
"emoticon",
"redo",
],
colors: ["#000000", "#eeece0", "#1c487f", "#4d80bf", "#f7acbc", "#5f5d46", "#deab8a", "#fedcbd", "#f0dc70", "#ef5b9c", "#7fb80e", "#d71345", "#aa363d", "#cbc547", "#0c212b", "#8a8c8e"],
initEmotions: {
title: "笑脸", // tab 的标题
type: "emoji", // 'emoji' / 'image'
content: " ☹ ☠ ".split(
/\s/
),
},
}
创建一个vue文件:
<template>
<div class="ED">
<div ref="editor" :id="id"></div>
</div>
</template>
<script>
import {
onMounted,
defineComponent,
onBeforeUnmount,
ref,
reactive,
watchEffect,
} from "vue";
// 引入wangeditor组件
import WangEditor from "wangeditor";
// 引入代码高亮组件
// import hljs from "highlight.js";
import config from "./config.js";
export default defineComponent({
name: "Wangeditor",
props: {
contentHtml: {
type: String,
default: "",
},
id: {
type: String,
default: "editor",
},
},
components: { Dialog, ImageList },
setup(props, content) {
const state = reactive({
editorData: "",
menus: config.menus,
initEmotions: config.initEmotions,
colors: config.colors,
dialogVisible: false,
isShow: false,
show: false,
});
// 获取编辑器实例html
const editor = ref();
// 编辑器实例对象
let instance = "";
onMounted(() => {
// 编辑器实例对象
instance = new WangEditor(editor.value);
// instance = new WangEditor("#" + props.id);
instance.config.colors = state.colors;
let emotionsLis = [];
emotionsLis.push(state.initEmotions);
instance.config.emotions = emotionsLis;
// 自定义菜单
instance.config.menus = state.menus;
// 代码高亮
// instance.highlight = hljs;
// 开启本地上传图片(这是后端上传链接)
// instance.config.uploadImgServer = "/upload-img";
// 限制上传图片格式
// instance.config.uploadImgAccept = ["jpg", "jpeg", "png", "gif", "bmp"];
// 开启本地上传视频(这是后端上传链接)
// instance.config.uploadVideoServer = "/api/upload-video";
// 设置编辑器高度
instance.config.height = 500;
// 设置编辑器页面层级
instance.config.zIndex = 10;
// 设置编辑器placeholder
instance.config.placeholder = "请输入您的文字!";
// 忽略粘贴内容中的图片
instance.config.pasteIgnoreImg = true;
instance.config.customUploadImg = (files, insert) => {
console.log(files);
// 这里用自己的上传方式上传图片
insert("");
};
// let changeRadio = (data) => {
// console.log(data);
// };
Object.assign(instance.config, {
// wangeditor 值发生变化的时候
onchange() {
// 将值instance.txt.html() 传递至父组件
// console.log(instance.txt.html());
content.emit("update:contentHtml", instance.txt.html());
},
// 上传网络图片回调
// linkImgCallback(src) {
// console.log("图片 src ", src);
// },
// 上传网络视频回调
onlineVideoCallback(video) {
// 自定义回调内容,内容成功插入后会执行该函数
console.log("插入视频内容", video);
},
});
instance.create();
// 设置富文本编辑器的页面内容,父组件传递的
instance.txt.html(props.contentHtml);
function initData() {
instance.txt.html(props.contentHtml);
}
watchEffect(initData);
});
// 页面卸载
onBeforeUnmount(() => {
instance.destroy();
instance = null;
});
return {
editor,
};
},
});
</script>
代码如下(示例):
<template>
<div style="border: 1px solid #ccc">
<Toolbar
:editorId="id"
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:mode="mode"
:defaultConfig="toolbarConfig"
/>
<Editor
:editorId="id"
style="min-height: 500px"
v-model="valueHtml"
:defaultConfig="editorConfigNew"
@onChange="handleChange"
:mode="mode"
@onCreated="handleCreated"
@onFocus="handleFocus"
@customPaste="customPaste"
/>
</div>
</template>
<script>
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import {
defineComponent,
onBeforeUnmount,
ref,
shallowRef,
onMounted,
} from "vue";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
export default defineComponent({
props: {
contentHtml: {
type: String,
default: "",
},
id: {
type: String,
default: "editor",
},
},
components: { Editor, Toolbar },
setup(props, content) {
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef();
const editor = shallowRef();
// 内容 HTML
const valueHtml = ref("");
const toolbarConfig = {
// excludeKeys: ["uploadVideo", "uploadImage", "fullScreen"],
excludeKeys: ["uploadVideo", "fullScreen"],
};
const editorConfigNew = { placeholder: "请输入内容...", MENU_CONF: {} };
editorConfigNew.MENU_CONF["uploadImage"] = {
// 自定义上传
async customUpload(file, insertFn) {
// file 即选中的文件
// 自己实现上传,并得到图片 url alt href
// 最后插入图片
// insertFn(url, alt, href);
// console.log(file)
insertFn(
""
);
},
};
// editorConfig.MENU_CONF["uploadImage"] = {
// // 自定义选择图片
// customBrowseAndUpload(insertFn) {
// // 自己选择文件
// // 自己上传文件,并得到图片 url alt href
// // 最后插入图片
// insertFn(url, alt, href);
// },
// };
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
const handleCreated = (editor) => {
// console.log("created", editor.getAllMenuKeys());
// console.log("created", editor);
editorRef.value = editor;
};
const handleChange = () => {
const editor = editorRef.value; // 获取 editor ,必须等待它渲染完之后
if (editor == null) return;
content.emit("update:contentHtml", editor.getHtml());
};
const handleFocus = () => {};
const customPaste = (editor, event, callback) => {
let text = event.clipboardData.getData();
// console.log("ClipboardEvent 粘贴事件对象", event);
// 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(text);
// 返回 false ,阻止默认粘贴行为
event.preventDefault();
callback(false); // 返回值(注意,vue 事件的返回值,不能用 return)
// 返回 true ,继续默认的粘贴行为
// callback(true)
};
onMounted(() => {});
const insertText = (val) => {
const editor = editorRef.value;
if (editor == null) return;
editor.dangerouslyInsertHtml(val);
};
return {
editorRef,
valueHtml,
mode: "default", // 或 'simple','default'
toolbarConfig,
editorConfigNew,
handleCreated,
handleChange,
handleFocus,
customPaste,
editor,
insertText,
};
},
data() {
return {};
},
methods: {},
});
</script>
<style lang="scss" scoped>
</style>
以上是两种版本的示例代码