Vue3 中使用富文本编辑器 wangeditor
·
Vue3中使用富文本编辑器 wangeditor
一、概述
在Vue3项目中使用wangEditor富文本编辑器,提供完整的文本编辑、图片上传、视频上传等功能。wangEditor是一款轻量级、功能丰富的Web富文本编辑器,特别适合Vue3项目集成。
二、实现步骤
2.1 安装依赖
官网地址 wangEditor5官网
yarn add @wangeditor/editor
# 或者 npm install @wangeditor/editor --save
yarn add @wangeditor/editor-for-vue@next
# 或者 npm install @wangeditor/editor-for-vue@next --save
2.2 组件封装
完整组件代码
<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css'
import { Editor, InsertFnType, Toolbar } from '@wangeditor/editor-for-vue'
import { getEnv, resolveBaseUrl } from '@nofar-core/utils'
//用于父组件接收wangeditor实时编辑的内容
const emits = defineEmits(['update:modelValue', 'change'])
const props = defineProps({
//用于做数据回显
modelValue: {
type: String,
default: ''
},
contentHeight: {
type: String,
default: '300px'
}
})
//内容HTML
const valueHtml = computed({
get() {
return props.modelValue
},
set(value: string) {
emits('update:modelValue', value)
}
})
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef()
//工具栏模式
const mode = ref('default')
//工具栏配置项
const toolbarConfig = {
excludeKeys: []//排除不需要的菜单
// 添加字体配置
}
interface MenuConf {
uploadImage?: any
uploadVideo?: any
[key: string]: any
}
//编辑器配置项
const editorConfig = {
placeholder: '请输入内容...',
MENU_CONF: {} as MenuConf
// 添加字体和字号配置
}
const { accessToken } = useToken()
const baseUrl = getEnv('BASE_API') ?? '/api'
interface UploadResponse {
body: {
filePath: string
}
}
// 修改 uploadImage 配置
editorConfig.MENU_CONF['uploadImage'] = {
// 服务端地址,必填
server: `${baseUrl}/AuthorityServer/file/upload`,
fieldName: 'file',
// 单个文件的最大体积限制,默认为 2M
maxFileSize: 50 * 1024 * 1024, // 50M
// 最多可上传几个文件,默认为 100
maxNumberOfFiles: 1,
// 跨域是否传递 cookie ,默认为 false
withCredentials: true,
// 自定义增加 http header
headers: {
Authorization: accessToken,
From: 'web'
},
// 超时时间,默认为 10 秒
timeout: 15 * 1000, // 15s
// 自定义插入图片
customInsert(res: UploadResponse, insertFn: InsertFnType) {
const url = resolveBaseUrl(res.body.filePath)
;(insertFn as (url: string, alt: string) => void)(url, '')
}
}
// 修改 uploadVideo 配置
editorConfig.MENU_CONF['uploadVideo'] = {
server: `${baseUrl}/AuthorityServer/file/upload`,
fieldName: 'file',
maxFileSize: 50 * 1024 * 1024,
maxNumberOfFiles: 1,
withCredentials: true,
headers: {
Authorization: accessToken,
From: 'web'
},
timeout: 15 * 1000,
customInsert(res: UploadResponse, insertFn: InsertFnType) {
const url = resolveBaseUrl(res.body.filePath)
;(insertFn as (url: string, alt: string) => void)(url, '')
}
}
// 组件销毁时,也及时销毁编辑器,重要!
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor == null) return
editor.destroy()
})
// 编辑器回调函数
const handleCreated = (editor: any) => {
editorRef.value = editor // 记录 editor 实例,重要!
}
function handleChange(editor: { getHtml: () => any }) {
emits('change', editor.getHtml())
}
</script>
<template>
<div class="editor_box z-[1] border-1 border-color-[#ccc]">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:default-config="toolbarConfig"
:mode="mode" />
<Editor
v-model="valueHtml"
:style="'height:' + contentHeight"
:default-config="editorConfig"
:mode="mode"
@on-change="handleChange"
@on-created="handleCreated" />
</div>
</template>
<style lang="scss">
.editor_box {
border-radius: 8px;
h1 {
font-size: 2em;
font-weight: bold;
}
h2 {
font-size: 1.5em;
font-weight: bold;
}
h3 {
font-size: 1.17em;
font-weight: bold;
}
h4 {
font-size: 1em;
font-weight: bold;
}
h5 {
font-size: 0.83em;
font-weight: bold;
}
}
.w-e-toolbar {
// background-color: #e4e7ed;
border-radius: 8px 8px 0 0;
}
.w-e-text-container {
border-radius: 8px;
}
.w-e-scroll {
border-radius: 8px;
}
</style>
模板说明:
- Toolbar:独立的工具栏组件
- Editor:编辑器主题组件
- 采用上下布局:工具栏 + 编辑区域
参数说明:
- modelValue:实现v-model双向绑定的值
- contentHeight:编辑器高度,默认为300px
- update:modelValue:v-model更新事件
- change:内容变化回调事件
关键技术:
- computed + get/set:用于创建支持 v-model 的可复用表单组件(它让组件可以像原生表单元素一样使用 v-model,提高了组件的复用性和易用性。)
- shallowRef:浅层响应式引用,适合编辑器实例
- mode:支持’default’和’simple’两种模式
2.3 在父组件中使用
<script setup lang="ts">
import Editor from '@/components/Editor/index.vue'
const form = reactive<Partial<AlertProcess>>({
remark: '',
name: ''
})
const handleSubmit = () => {
console.log('提交数据:', form)
// 提交逻辑...
}
</script>
<template>
<el-dialog draggable>
<el-form ref="formRef" :model="form" label-width="auto" :rules="rules">
<el-form-item label="广告名称" prop="name">
<el-input v-model="form.name" resize="none"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<Editor v-model="form.remark" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">取消 </el-button>
<el-button type="primary" @click="handleSubmit"> 确定</el-button>
</template>
</el-dialog>
</template>
2.4 实现效果
编辑器
更多推荐



所有评论(0)