前言:wangEditor 官网 。本文档讲解 wangEditor 在 vue3 中的使用。
一:快速开始
1. 安装
需要安装 @wangeditor/editor、@wangeditor/editor-for-vue@next 两个依赖
# 安装 editor npm install @wangeditor/editor # or yarn add @wangeditor/editor # or pnpm add @wangeditor/editor # 安装 Vue3 组件 npm install @wangeditor/editor-for-vue@next # or yarn add @wangeditor/editor-for-vue@next # or pnpm add @wangeditor/editor-for-vue@next
2. 构建组件 components/Rich.vue
<script setup lang="ts"> import "@wangeditor/editor/dist/css/style.css"; // 引入 css import { onBeforeUnmount, ref, shallowRef, computed } from "vue"; import { Editor, Toolbar } from "@wangeditor/editor-for-vue"; const props = defineProps({ modelValue: { type: String, required: true, }, toolbarConfig: { type: Object, default: {}, }, editorConfig: { type: Object, default: { placeholder: "请输入内容...", }, }, height: { type: String, default: "300px", }, }); const emits = defineEmits(["update:modelValue"]); let valueHtml = computed({ get() { return props.modelValue; }, set(value) { emits("update:modelValue", value); }, }); let style: any = computed(() => { return { height: props.height, "overflow-y": "hidden", }; }); // 编辑器实例,必须用 shallowRef const editorRef = shallowRef(); // 模式 let mode = ref("default"); // 组件销毁时,也及时销毁编辑器 onBeforeUnmount(() => { const editor = editorRef.value; if (editor == null) return; editor.destroy(); }); const handleCreated = (editor: any) => { editorRef.value = editor; // 记录 editor 实例,重要! }; </script> <template> <div class="editor-content-view"> <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" /> <Editor :style="style" v-model="valueHtml" :defaultConfig="editorConfig" :mode="mode" @onCreated="handleCreated" /> </div> </template> <style lang="scss" scoped> .editor-content-view { border: 1px solid #ccc; z-index: 999; } </style>
3. 使用 Rich.vue 组件
<script setup lang="ts"> import { ref } from "vue"; import Rich from "@/components/Rich.vue"; let richHtml = ref(""); </script> <template> <div class="page-rich"> <Rich v-model="richHtml" /> </div> </template> <style lang="scss" scoped></style>
二:优势
使用 slate.js(但不依赖 React)为内核、强稳定性、高扩展性、有详细中文文档、可直接使用无需二次开发、不依赖框架。
三:基础
1. 定义 CSS
可自定义编辑器、工具栏的尺寸、边框、z-index 等样式。
<template> <!-- 边框 --> <div class="editor-content-view"> <!-- 工具栏 --> <Toolbar style="border-bottom: 1px solid #ccc" /> <!-- 编译器 --> <Editor style="height: 500px; overflow-y: hidden" /> </div> </template> <style lang="scss" scoped> .editor-content-view { border: 1px solid #ccc; z-index: 999; } </style>
2. 定义 HTML
如果想要“全屏”功能,则要求工具栏、编辑器 DOM 节点必须是同一层级,同时父级盒子设置 z-index: 999。
<template> <div class="editor-content-view"> <!-- 工具栏 --> <Toolbar /> <!-- 编译器 --> <Editor /> </div> </template> <style lang="scss" scoped> .editor-content-view { z-index: 999; } </style>
3. 模式
通过设置 mode 改变富文本模式,'default' 默认模式,基础所有功能。'simple' 简洁模式,仅有常用功能。
<script setup lang="ts"> // 模式 let mode = ref("default"); </script> <template> <div class="editor-content-view"> <Toolbar :mode="mode" /> <Editor :mode="mode" /> </div> </template>
四:在 vue3 中使用
1. 配置
可通过 toolbarConfig 和 editorConfig 来修改菜单栏和编辑器的配置。注意:编辑器配置中 onXxx 格式的生命周期函数,必须通过 Vue 事件来传递,不可以放在 editorConfig 中
<script setup lang="ts"> const props = defineProps({ toolbarConfig: { type: Object, default: {}, }, editorConfig: { type: Object, default: { placeholder: "请输入内容...", }, }, }); const handleCreated = (editor: any) => { editorRef.value = editor; // 记录 editor 实例,重要! }; </script> <template> <div class="editor-content-view"> <Toolbar :defaultConfig="toolbarConfig" /> <Editor :defaultConfig="editorConfig" @onCreated="handleCreated" /> </div> </template> <style lang="scss" scoped> .editor-content-view { border: 1px solid #ccc; z-index: 999; } </style>
2. 调用 API
当编辑器渲染完成之后,通过 editorRef.value 获取 editor 实例,即可调用它的 API 。
// 组件销毁时,也及时销毁编辑器 onBeforeUnmount(() => { const editor = editorRef.value; if (editor == null) return; editor.destroy(); });
五:配置和 API
下面代码例子,都是以 components/Rich.vue 作为例子的基础上扩展功能。
1. 工具栏配置
1.1 getConfig
通过 toolbar.getConfig() 查看工具栏的默认配置
import { DomEditor } from "@wangeditor/editor"; const handleCreated = (editor) => { const toolbar = DomEditor.getToolbar(editor); const result = toolbar.getConfig(); console.log(result); };
1.2 toolbarKeys
重新配置工具栏,显示哪些菜单,以及菜单的排序、分组。可以通过 toolbar.getConfig().toolbarKeys 查看当前的默认配置。
<script setup lang="ts"> import { ref } from "vue"; import Rich from "@/components/Rich.vue"; let richHtml = ref("asdf"); let toolbarConfig = { toolbarKeys: [ // 菜单 key "headerSelect", // 分割线 "|", // 菜单 key "bold", "italic", ], insertKeys: { index: 1, // 插入的位置,基于当前的 toolbarKeys keys: ["color", "bgColor"], }, }; </script> <template> <div class="page-rich"> <Rich v-model="richHtml" :toolbarConfig="toolbarConfig" /> </div> </template>
1.3 insertKeys
在当前 toolbarKeys 的基础上继续插入新菜单,如自定义扩展的菜单。
<script setup lang="ts"> import { ref } from "vue"; import Rich from "@/components/Rich.vue"; let richHtml = ref("asdf"); let toolbarConfig = { toolbarKeys: [ // 菜单 key "headerSelect", // 分割线 "|", // 菜单 key "bold", "italic", ], insertKeys: { index: 1, // 插入的位置,基于当前的 toolbarKeys keys: ["color", "bgColor"], }, }; </script> <template> <div class="page-rich"> <Rich v-model="richHtml" :toolbarConfig="toolbarConfig" /> </div> </template>
1.4 excludeKeys
排除掉某些菜单
<script setup lang="ts"> import { ref } from "vue"; import Rich from "@/components/Rich.vue"; let richHtml = ref("asdf"); let toolbarConfig = { toolbarKeys: [ // 菜单 key "headerSelect", // 分割线 "|", // 菜单 key "bold", "italic", ], insertKeys: { index: 1, // 插入的位置,基于当前的 toolbarKeys keys: ["color", "bgColor"], }, excludeKeys: ["headerSelect"], }; </script> <template> <div class="page-rich"> <Rich v-model="richHtml" :toolbarConfig="toolbarConfig" /> </div> </template>
2. 编辑器配置
2.1 getConfig
通过 editor.getConfig() 查看工具栏的默认配置
const handleCreated = (editor) => { const result = editor.getConfig(); console.log(result); };
2.2 editorConfig 配置
<script setup lang="ts"> import { ref } from "vue"; import Rich from "@/components/Rich.vue"; let richHtml = ref(""); let editorConfig = ref({ placeholder: "请输入", readOnly: false, // 是否只读,默认 false autoFocus: true, // 是否focus, 默认 true scroll: true, // 是否支持滚动,默认true。不要固定 editor-container 的高度,设置一个 min-height 即可。 maxLength: 20, // 最高内容长度,onMaxLength 当达到限制时,触发函数 }); </script> <template> <div class="page-rich"> <Rich v-model="richHtml" :editorConfig="editorConfig" /> </div> </template>
2.3 编译器方法
<script setup lang="ts"> // 编辑器创建完毕时的回调函数。 const handleCreated = (editor) => { editorRef.value = editor; console.log("created", editor); }; // 编辑器内容、选区变化时的回调函数。 const handleChange = (editor) => { console.log("change:", editor.children); }; // 编辑器销毁时的回调函数。调用 editor.destroy() 即可销毁编辑器 const handleDestroyed = (editor) => { console.log("destroyed", editor); }; // 编辑器 focus 时的回调函数。 const handleFocus = (editor) => { console.log("focus", editor); }; // 编辑器 blur 时的回调函数。 const handleBlur = (editor) => { console.log("blur", editor); }; // 自定义编辑器 alert 。 const customAlert = (info, type) => { alert(`【自定义提示】${type} - ${info}`); }; // 自定义粘贴。可阻止编辑器的默认粘贴,实现自己的粘贴逻辑。 const customPaste = (editor, event, callback) => { 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("xxx"); // 返回 false ,阻止默认粘贴行为 event.preventDefault(); callback(false); // 返回值(注意,vue 事件的返回值,不能用 return) // 返回 true ,继续默认的粘贴行为 // callback(true) }; </script> <template> <div class="editor-content-view"> <Toolbar /> <Editor @onCreated="handleCreated" @onChange="handleChange" @onDestroyed="handleDestroyed" @onFocus="handleFocus" @onBlur="handleBlur" @customAlert="customAlert" @customPaste="customPaste" /> </div> </template>
wangEditor 富文本详解(中)https://developer.aliyun.com/article/1513310?spm=a2c6h.13148508.setting.31.f8774f0euyBLtl