《tinymce》一个非常适用于vue的编辑器、它在gitHub上的星星已经突破10k大关︿( ̄︶ ̄)︿
首先我们的技术选型是 Vite2.0以上+Vue3.0 使用的是JS来引入TinyMce
1.npm安装tinymce
//执行代码,安装最新版tinymce5.0
npm install @tinymce/tinymce-vue -S
2.新建文件TinyMce.vue文件
//HTML部分
<template>
<editor v-model="myValue" :init="init"></editor>
</template>
//JS部分
//在js中引入所需的主题和组件
<script setup>
import tinymce from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver'
</script>
3.在其他页面使用我们刚才定义好的组件
<TinyMCE :value="tinymce.value" @getContent="tinymce.getContent"></TinyMCE>
//getContent是我们编辑器指定暴露出来的方法,外部可以定义一个方法来接收富文本中的数据。
4.接下来我们要配置我们编辑器的插件以及内部的一些监听方法
//在TinyMce.vue中接着引入相关插件
import "tinymce/icons/default/icons"
import "tinymce/plugins/image" // 插入上传图片插件
import "tinymce/plugins/media" // 插入视频插件
import "tinymce/plugins/table" // 插入表格插件
import "tinymce/plugins/lists" // 列表插件
import "tinymce/plugins/wordcount" // 字数统计插件
import "tinymce/plugins/code" // 源码
import "tinymce/plugins/fullscreen" //全屏
//接下来定义编辑器所需要的插件数据
import {
reactive, ref } from "vue"
import {
onMounted, defineEmits, watch } from "@vue/runtime-core"
const emits = defineEmits(["getContent"])
//这里我选择将数据定义在props里面,方便在不同的页面也可以配置出不同的编辑器,当然也可以直接在组件中直接定义
const props = defineProps({
value: {
type: String,
default: () => {
return ""
},
},
baseUrl: {
type: String,
default: "",
},
disabled: {
type: Boolean,
default: false,
},
plugins: {
type: [String, Array],
default: "lists image media table wordcount fullscreen",
},//必填
toolbar: {
type: [String, Array],
default:
"undo redo | formatselect | bold italic forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image media table code | removeformat | fullscreen",
},//必填
})
//用于接收外部传递进来的富文本
const myValue = ref(props.value)
5.我们所需要的插件以及数据都已经准备好了
开始真正的配置我们的编辑器
//定义一个对象 init初始化
const init = reactive({
language_url: "../../node_modules/tinymce/langs/zh_CN.js", // 语言包的路径,具体路径看自己的项目,文档后面附上中文js文件
language: "zh_CN", //语言
skin_url: "../../node_modules/tinymce/skins/ui/oxide", // skin路径,具体路径看自己的项目
height: 500, //编辑器高度
branding: false, //是否禁用“Powered by TinyMCE”
menubar: true, //顶部菜单栏显示
image_dimensions: false, //去除宽高属性
plugins: props.plugins, //这里的数据是在props里面就定义好了的
toolbar: props.toolbar, //这里的数据是在props里面就定义好了的
paste_convert_word_fake_lists: false, // 插入word文档需要该属性
paste_webkit_styles: "all",
paste_merge_formats: true,
nonbreaking_force_tab: false,
paste_auto_cleanup_on_paste: false,
//图片上传
images_upload_handler: (blobInfo, success, failure) => {
let formdata = new FormData()
formdata.append("ifle", blobInfo.blob())
// 这里是上传文件的方法
axops.post('xxxxx',formdata).then(res=>{
})//大家用自己的上传方法就好啦
success("http://asuhiaufgijasbfiuojnsfo.png") //将返回来的数据放在succsss回调中、这里是示例
},
//文件上传
file_picker_callback: function (callback, value, meta) {
//文件分类
var filetype = ".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4"
//模拟出一个input用于添加本地文件
var input = document.createElement("input")
input.setAttribute("type", "file")
input.setAttribute("accept", filetype)
input.click()
input.onchange = function () {
var file = this.files[0]
var formdata = new FormData()
formdata.append("file", file)
axops.post('xxxxx',formdata).then(res=>{
})//一样、大家用自己的上传方法就好啦
//返回地址
callback("http://baidu.com", {
title: file.name }) //将返回的数据放在callback()里面、这里是示例
}
},
})
//监听外部传递进来的的数据变化
watch(
() => props.value,
() => {
myValue.value = props.value
emits("getContent", myValue.value)
}
)
//监听富文本中的数据变化
watch(
() => myValue.value,
() => {
emits