这个用来记录我使用TinyMce富文本编辑器时遇到的一些问题
1.加载空白,不渲染问题
2.路由跳转以后,页面空白问题
首先我是看了其他的两篇帖子,最后找到了解决方案
https://juejin.cn/post/6921986236408152077
https://blog.csdn.net/m0_73358221/article/details/129358814#comments_30465890
1.加载空白,不渲染问题
我是使用npm的方式安装的TinyMce。
版本分别是
"dependencies": {
"@tinymce/tinymce-vue": "^5.1.1",
"tinymce": "^6.8.2"
}
将安装好的文件复制到public里面
然后在富文本初始化的时候加入一行
skin_url: '../tinymce/skins/ui/oxide',
路径就是复制到public里文件的路径,每个人可能都不一样
2.路由跳转以后,页面空白问题
这个问题的具体原因我也不是很清楚,应该就是销毁了,但是没有完全销毁,所以组件没有进行重新初始化。
解决方法:给组件上一个唯一id
const id = 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
下面贴上我的完整代码:
首先是组件页面:TinyMce.vue
<template>
<textarea :id="id" style="width: 100%"></textarea>
</template>
<script setup>
import tinymce from 'tinymce/tinymce'; //tinymce核心文件
import 'tinymce/models/dom'; // 引入dom模块。从 Tinymce6,开始必须有此模块导入
import 'tinymce/themes/silver'; //默认主题
import 'tinymce/icons/default/icons.min.js'; //引入编辑器图标icon,不引入则不显示对应图标
import '/public/tinymce/langs/zh-Hans'; //引入编辑器语言包
/* 引入编辑器插件
* 位于 ./node_modules/tinymce/plugins 目录下,版本不同,插件会有所差异。根据自己版本来导入,若不存在的,不能导入,会报错。
*/
import 'tinymce/skins/ui/oxide/skin.min.css'
import 'tinymce/plugins/advlist'; //高级列表
import 'tinymce/plugins/anchor'; //锚点
import 'tinymce/plugins/autolink'; //自动链接
import 'tinymce/plugins/autoresize'; //编辑器高度自适应,注:plugins里引入此插件时,Init里设置的height将失效
/**
* 这个组件会在你刷新或路由跳转时出现一个弹窗提示。我不需要所以注释掉
*/
//import 'tinymce/plugins/autosave'; //自动存稿
import 'tinymce/plugins/charmap'; //特殊字符
import 'tinymce/plugins/code'; //编辑源码
import 'tinymce/plugins/codesample'; //代码示例
import 'tinymce/plugins/directionality'; //文字方向
import 'tinymce/plugins/emoticons'; //表情
import 'tinymce/plugins/fullscreen'; //全屏
import 'tinymce/plugins/help'; //帮助
import 'tinymce/plugins/image'; //插入编辑图片
import 'tinymce/plugins/importcss'; //引入css
import 'tinymce/plugins/insertdatetime'; //插入日期时间
import 'tinymce/plugins/link'; //超链接
import 'tinymce/plugins/lists'; //列表插件
import 'tinymce/plugins/media'; //插入编辑媒体
import 'tinymce/plugins/nonbreaking'; //插入不间断空格
import 'tinymce/plugins/pagebreak'; //插入分页符
import 'tinymce/plugins/preview'; //预览
import 'tinymce/plugins/quickbars'; //快速工具栏
import 'tinymce/plugins/save'; //保存
import 'tinymce/plugins/searchreplace'; //查找替换
import 'tinymce/plugins/table'; //表格
import 'tinymce/plugins/template'; //内容模板
import 'tinymce/plugins/visualblocks'; //显示元素范围
import 'tinymce/plugins/visualchars'; //显示不可见字符
/**
* 字数统计有bug,所以先注释掉
*/
//import 'tinymce/plugins/wordcount'; //字数统计
import {onMounted, onUnmounted} from "vue";
/**
* 每次加载组件时,都会生成一个唯一id
*/
const id = 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
const tinyInit = () => {
console.log(`#${id}`)
tinymce.init({
selector: `#${id}`,
language: 'zh-Hans',
promotion: false, //Upgrade是否开启
branding: false, //tiny技术支持信息是否显示
skin_url: '../tinymce/skins/ui/oxide',
plugins: 'codesample preview searchreplace autolink directionality visualblocks visualchars image link media template table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave', //使用image插件
menu: {
file: {title: '文件', items: 'newdocument'},
edit: {title: '编辑', items: 'undo redo | cut copy paste pastetext | selectall'},
insert: {title: '插入', items: 'image link media | template hr'},
view: {title: '查看', items: 'visualaid'},
format: {
title: '格式',
items: 'bold italic underline strikethrough superscript subscript | formats | removeformat'
},
table: {title: '表格', items: 'inserttable tableprops deletetable | cell row column'},
tools: {title: '工具', items: 'spellchecker code'},
},
toolbar: 'preview codesample code forecolor backcolor styles directionality fontfamily fontsize searchreplace image media link alignleft aligncenter alignright template table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave ', //工具栏显示
line_height_formats: '1 1.2 1.4 1.6 2', //行高
font_size_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', //字体大小
font_family_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;',
file_browser_callback_types: 'file image media',//这个根据个人需要配置
file_picker_callback: function (callback, value, meta) {
console.log(meta.filetype) //打印上传的类型
// // 要先模拟出一个input用于上传本地文件
var input = document.createElement('input')
input.setAttribute('type', 'file')
// 你可以给input加accept属性来限制上传的文件类型
// 例如:input.setAttribute('accept', '.jpg,.png')
input.setAttribute('accept', '.ppt,.pptx,.jpg, .jpeg, .png, .gif,.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx,.mp3, .mp4')
input.click()
input.onchange = function () {
var file = this.files[0]
// 下方被注释掉的是官方的一个例子
// 放到下面给大家参考
var reader = new FileReader()
reader.onload = function () {
console.log(window.tinymce) //打印tinymce编辑器里面的参数
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
var id = 'blobid' + (new Date()).getTime()
var blobCache = window.tinymce.activeEditor.editorUpload.blobCache
var base64 = reader.result.split(',')[1]
var blobInfo = blobCache.create(id, file, base64)
blobCache.add(blobInfo) //
// call the callback and populate the Title field with the file name
callback(blobInfo.blobUri(), {text: file.name, title: file.name})
}
reader.readAsDataURL(file)
}
},
init_instance_callback: function (editor) {
console.log('Editor initialized', editor);
console.log("初始化完成");
},
})
}
/**
* 将数据放入
*/
const setContents = (newContent) => {
const editor = tinymce.get(id);
if (editor) {
editor.setContent(newContent);
}
};
/**
* 获得数据
*/
const getContents = () => {
const editor = tinymce.get(id);
if (editor) {
return editor.getContent()
}
};
/**
* 组件销毁
*/
const removeTiny = () => {
const editor = tinymce.get(id);
if (editor) {
editor.destroy()
}
}
onMounted(() => {
tinyInit()
});
/**
* 当加载组件的页面退出、关闭或跳转到其他页面时,自动销毁组件
*/
onUnmounted(() => {
console.log("组件销毁=》removeTiny")
removeTiny()
})
// eslint-disable-next-line no-undef
defineExpose({
setContents,
getContents,
removeTiny,
tinyInit
})
</script>
<style scoped>
</style>
然后是组件的调用:test.vue
<template>
<div>
<TinyMce ref="tinyMce" />
<el-button @click="testT" >功能测试</el-button>
<el-button @click="testS">输入测试</el-button>
<el-button @click="testC">输出测试</el-button>
</div>
</template>
<script setup>
import TinyMce from '@/components/TinyMce.vue'
import {ref} from "vue";
const tinyMce = ref('')
const testT = () => {
tinyMce.value.testFunction()
}
const testS = () => {
tinyMce.value.setContents('<h1>测试功能</h1>')
}
const testC = () => {
console.log(tinyMce.value.getContents())
}
</script>
<style scoped>
</style>
运行:
输入功能:
输出数据:
有问题的话,可以直接评论区留言。
2024-01-25:在实际使用中发现了一些问题,现在做出修改->const editor = tinymce.get(id);定义为全局
撤回01-25的修改,会导致组件方法无法使用