近期后台项目有使用富文本编辑器的需求,本文记录一下封装细节
以上即是一些常见常用的富文本组件库,各组件库优缺点都有,具体就不详细踩坑分析。作者使用TinyMCE作为实例。
文档地址:TinyMCE中文文档 | TinyMCE官方文档
pnpm add tinymce@^5 @tinymce/tinymce-vue
<template>
<div class="richtext-container">
<Editor
id="myedit"
v-model="content"
:init="initProps"
:disabled="readonly"
/>
</div>
</template>
<script setup lang="ts">
import {reactive, ref, onMounted, watch, watchEffect} from 'vue'
import tinymce from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
import QiniuUpload from '@/utils/qnUpload'// 图片上传方法自行实现
// UI资源相关
import "tinymce/themes/silver"
import "tinymce/icons/default"
import "tinymce/icons/default/icons"
// 插件
import 'tinymce/plugins/image'
import 'tinymce/plugins/paste' //粘贴图片上传请务必引入此插件
const props = defineProps({
modelValue:{
type: String,
default: ""
},
height:{
type: Number,
default: 278
},
readonly:{
type: Boolean,
default: true
}
})
const emits = defineEmits(['update:modelValue'])
let content = ref()
const initProps = reactive({
selector: '#myedit',
readonly: props.readonly,
height: props.height,
resize: false,
language_url: "/tinymce/langs/zh-Hans.js", //语言包路径
language: "zh-Hans", //语言
skin_url: "/tinymce/skins/ui/custom", // 定制样式资源路径
content_css: '/tinymce/skins/ui/custom/content.min.css', // 定制样式资源路径
branding: false,
menubar: false,
toolbar_sticky: true,
toolbar_groups: false,
elementpath: false,
toolbar: `undo redo bold italic underline strikethrough
removeformat subscript superscript | alignleft
aligncenter alignright alignjustify outdent indent |
paste image`,
plugins: 'image paste',
paste_data_images: true,
// 图片上传处理
images_upload_handler: async(blobInfo:any, succFun:any, failFun:any)=>{
let file = blobInfo.blob()
try {
const data:any = await QiniuUpload(file,'image','xxx')
succFun(data?.real_url)
} catch (error) {
failFun(error)
}
},
})
onMounted(() => {tinymce.init({})})
watchEffect(()=>{
content.value = props.modelValue
})
watch(content,()=>{
updateData()
})
const updateData = ()=>{
emits('update:modelValue',content.value)
}
</script>
<style lang="less" scoped>
.richtext-container{
:deep(.tox){
.tox-statusbar{
display: none;
}
}
}
</style>
<template>
<div>
<my-richText v-model="richText" :readonly="false"></my-richText>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
let richText = ref('哈哈哈哈呵呵呵呵
')
watch(richText,(val)=>{
console.log(val)
})
</script>