文章标题:Vue组件实现富文本编辑器
文章摘要:本文介绍了如何使用Vue和Wangeditor插件实现富文本编辑器组件,并详细解释了组件中的各个部分和功能。
Vue组件实现富文本编辑器 在Web开发中,富文本编辑器是一个非常常见的功能,它能够让用户以所见即所得的方式编辑和排版文本内容。本文将介绍如何使用Vue和Wangeditor插件实现一个富文本编辑器组件。
- 安装依赖 首先,我们需要安装@wangeditor/editor-for-vue插件,该插件提供了与Vue集成的富文本编辑器组件。可以通过以下命令来安装:
npm install @wangeditor/editor-for-vue
- 创建富文本编辑器组件 在Vue项目中,创建一个名为RichTextEditor的组件,用于展示富文本编辑器界面和处理相关逻辑。
组件模板代码如下:
html
<template>
<div v-if="newVisible">
<div class="container"></div>
<div style="border: 1px solid #ccc">
<!-- 工具栏 -->
<Toolbar
:editor="editorRef"
style="border-bottom: 1px solid #ccc"
:defaultConfig="toolbarConfig"
/>
<!-- 编辑器 -->
<Editor
v-model="valueHtml"
:defaultConfig="editorConfig"
style="height: 500px; overflow-y: hidden"
@onCreated="handleCreated"
/>
</div>
<div class="btn-container">
<CBotton type="primary" @click="save">保存</CBotton>
<CBotton type="dashed" @click="cancel">取消</CBotton>
</div>
</div>
</template>
在上述代码中,我们通过v-if指令控制编辑器组件的显示和隐藏。组件包含一个工具栏和一个编辑器,并在底部添加了保存和取消按钮。
- 定义组件的数据和方法在标签中,我们需要定义组件的数据和方法。首先,引入所需的依赖:
javascript
<script setup>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { uploadFile } from "@/api/base";
import { submitUploadInfoApi, getHelpContent } from "@/api/sale/help-set.ts";
import { message } from "ant-design-vue";
import {
onBeforeUnmount,
shallowRef,
defineProps,
ref,
computed,
defineEmits,
reactive,
watch,
} from "vue";
</script>
接着,定义组件需要的数据和方法:
javascript
// 编辑器实例,必须用 shallowRef,重要!
const editorRef = shallowRef();
const photoGalleryDialogVisible = ref();
const spinning = ref(false);
// 内容 HTML
const valueHtml = ref("");
const props = defineProps({
visible: { type: Boolean, default: false },
info: { type: Object, default: null },
content: { type: Object, default: null },
});
const emit = defineEmits(["confirm", "update:visible", "select"]);
const newVisible = computed({
get() {
// 传过来的一行
return props.visible;
},
});
watch(
() => props.visible,
(val) => {
console.log("val: ", props.info);
if (val) {
if (props?.content?.content) {
valueHtml.value = props.content.content;
}
} else {
}
}
);
const handleCreated = (editor) => {
editorRef.value = editor; // 记录 editor 实例,重要!
};
const save = async () => {
// 保存逻辑
const p = {
categoryId: props.info.id,
contentType: 1,
content: valueHtml.value,
};
const res = await submitUploadInfoApi(p);
if (res.code == 0) {
cancel();
emit("select", props.info.id);
return message.success(res.msg);
}
};
const cancel = () => {
// 取消逻辑
console.log("取消编辑");
emit("update:visible", false);
valueHtml.value = "";
};
// 组件销毁时,及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
</script>
在上述代码中,我们使用了Vue 3中的Composition API来定义组件的数据和方法。其中,editorRef用于保存编辑器实例,valueHtml用于存储编辑器中的HTML内容。
save方法用于保存编辑的内容,首先将内容发送到后端进行保存,并在保存成功后触发select事件。cancel方法用于取消编辑操作,清空内容并隐藏编辑器。
最后,我们使用onBeforeUnmount钩子函数,在组件销毁前及时销毁编辑器实例。
- 配置工具栏和编辑器 在上述代码中,我们还需要配置编辑器的工具栏和编辑器本身的相关属性。代码如下:
javascript
<script setup>
// 工具栏配置
const toolbarConfig = {
toolbarKeys: [
// 一些常用的菜单 key
"bold", // 加粗
"italic", // 斜体
"through", // 删除线
"underline", // 下划线
"bulletedList", // 无序列表
"numberedList", // 有序列表
"color", // 文字颜色
"fontSize", // 字体大小
"lineHeight", // 行高
"uploadImage", // 上传图片
"delIndent", // 缩进
"indent", // 增进
"deleteImage", //删除图片
"divider", // 分割线
"justifyCenter", // 居中对齐
"justifyJustify", // 两端对齐
"justifyLeft", // 左对齐
"justifyRight", // 右对齐
"undo", // 撤销
"redo", // 重做
"clearStyle", // 清除格式
],
};
// 编辑器配置
const editorConfig = {
placeholder: "",
MENU_CONF: {
uploadImage: {
server: uploadFile.url,
headers: { Authorization: uploadFile.Authorization },
"tenant-id": "1",
fieldName: "file",
customInsert(res, insertFn) {
if (res.code == 0) {
insertFn(res.data, null, res.data);
}
},
},
},
};
</script>
在上述代码中,我们通过toolbarConfig配置对象定义了工具栏的显示菜单,包括加粗、斜体、删除线、下划线、无序列表、有序列表、文字颜色、字体大小、行高、上传图片等功能。
editorConfig用于配置编辑器的相关属性,包括占位符文本(placeholder)以及上传图片的配置。
- 添加样式 最后,在组件的标签中,我们可以添加一些样式来美化富文本编辑器的界面。例如:
html
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style>
.btn-container {
display: flex;
justify-content: space-evenly;
align-items: center;
margin-top: 60px;
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
h1 {
text-align: center;
font-size: 28px;
}
</style>
以上代码中,我们引入了Wangeditor默认的样式文件,并自定义了一些样式来调整按钮容器和编辑器容器的布局。
- 使用富文本编辑器组件 完成以上步骤后,我们就可以在其他Vue组件中使用RichTextEditor组件了。例如:
html
<Editor
v-show="onsitesVisible"
:info="onsiteActive"
:content="content"
v-model:visible="onsitesVisible"
@confirm="getLists"
@select="selects"
/>
在上述代码中,我们将RichTextEditor组件作为子组件引入,并通过:visible、:info和:content属性来传递组件需要的参数。同时,可以监听select事件来处理富文本编辑器中的选中操作。
结语 在本文中,我们介绍了如何使用Vue和Wangeditor插件实现一个富文本编辑器组件,并详细解释了组件中的各个部分和功能。通过这个组件,用户可以方便地进行富文本内容的编辑和排版。希望本文能对你理解和使用富文本编辑器有所帮助!
完整代码
html
<template>
<div v-if="newVisible">
<div class="container"></div>
<div style="border: 1px solid #ccc">
<!-- 工具栏 -->
<Toolbar
:editor="editorRef"
style="border-bottom: 1px solid #ccc"
:defaultConfig="toolbarConfig"
/>
<!-- 编辑器 -->
<Editor
v-model="valueHtml"
:defaultConfig="editorConfig"
style="height: 500px; overflow-y: hidden"
@onCreated="handleCreated"
/>
</div>
<div class="btn-container">
<CBotton type="primary" @click="save">保存</CBotton>
<CBotton type="dashed" @click="cancel">取消</CBotton>
</div>
</div>
</template>
<script setup>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { uploadFile } from "@/api/base";
import { submitUploadInfoApi, getHelpContent } from "@/api/sale/help-set.ts";
import { message } from "ant-design-vue";
import {
onBeforeUnmount,
shallowRef,
defineProps,
ref,
computed,
defineEmits,
reactive,
watch,
} from "vue";
// 编辑器实例,必须用 shallowRef,重要!
const editorRef = shallowRef();
const photoGalleryDialogVisible = ref();
const spinning = ref(false);
// 内容 HTML
const valueHtml = ref("");
const props = defineProps({
visible: { type: Boolean, default: false },
info: { type: Object, default: null },
content: { type: Object, default: null },
});
const emit = defineEmits(["confirm", "update:visible", "select"]);
const newVisible = computed({
get() {
// 传过来的一行
return props.visible;
},
});
watch(
() => props.visible,
(val) => {
console.log("val: ", props.info);
if (val) {
if (props?.content?.content) {
valueHtml.value = props.content.content;
}
} else {
}
}
);
const handleCreated = (editor) => {
editorRef.value = editor; // 记录 editor 实例,重要!
};
const save = async () => {
// 保存逻辑
const p = {
categoryId: props.info.id,
contentType: 1,
content: valueHtml.value,
};
const res = await submitUploadInfoApi(p);
if (res.code == 0) {
cancel();
emit("select", props.info.id);
return message.success(res.msg);
}
};
const cancel = () => {
// 取消逻辑
console.log("取消编辑");
emit("update:visible", false);
valueHtml.value = "";
};
// 组件销毁时,及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
// 工具栏配置
const toolbarConfig = {
toolbarKeys: [
// 一些常用的菜单 key
"bold", // 加粗
"italic", // 斜体
"through", // 删除线
"underline", // 下划线
"bulletedList", // 无序列表
"numberedList", // 有序列表
"color", // 文字颜色
"fontSize", // 字体大小
"lineHeight", // 行高
"uploadImage", // 上传图片
"delIndent", // 缩进
"indent", // 增进
"deleteImage", //删除图片
"divider", // 分割线
"justifyCenter", // 居中对齐
"justifyJustify", // 两端对齐
"justifyLeft", // 左对齐
"justifyRight", // 右对齐
"undo", // 撤销
"redo", // 重做
"clearStyle", // 清除格式
],
};
// 编辑器配置
const editorConfig = {
placeholder: "",
MENU_CONF: {
uploadImage: {
server: uploadFile.url,
headers: { Authorization: uploadFile.Authorization },
"tenant-id": "1",
fieldName: "file", // 这里有个坑,如果返回的响应结果是没有上传文件,跟这里关系很大
customInsert(res, insertFn) {
if (res.code == 0) {
insertFn(res.data, null, res.data);
}
},
},
},
};
</script>
<!-- 别忘了引入样式 -->
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style>
.btn-container {
display: flex;
justify-content: space-evenly;
align-items: center;
margin-top: 60px;
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
h1 {
text-align: center;
font-size: 28px;
}
</style>