发布时间:2025-12-09 12:05:44 浏览次数:2
下载 地址 : https://www.tiny.cloud/get-tiny/self-hosted/
语言包 地址: https://www.tiny.cloud/get-tiny/language-packages/
# vue2.0版本应该使用npm install --save "@tinymce/tinymce-vue@^3"# vue3.0版本应该使用npm install --save "@tinymce/tinymce-vue@^4"# 再运行 npm install tinymce -S安装之后,在 node_modules 中找到 tinymce/skins 目录,然后将 skins 目录拷贝到 static 目录下
结构 如: static
tinymceskinszh_CN.js在页面中引入以下文件
import tinymce from "tinymce/tinymce";import "tinymce/themes/silver/theme";import Editor from "@tinymce/tinymce-vue";import "tinymce/icons/default/icons";import "tinymce/plugins/media"; // 插入视频插件import "tinymce/plugins/image";import "tinymce/plugins/link";import "tinymce/plugins/code";import "tinymce/plugins/table";import "tinymce/plugins/lists";import "tinymce/plugins/contextmenu";import "tinymce/plugins/wordcount";import "tinymce/plugins/colorpicker";import "tinymce/plugins/textcolor";tinymce-vue 是一个组件,需要在 components 中注册,
components: { Editor },然后直接使用
<Editor v-model="tinymceHtml" :init="editorInit"></Editor>编辑器需要一个 skin 才能正常工作,所以要设置一个 skin_url 指向之前复制出来的 skin 文件
editorInit: { language_url: '/static/tinymce/zh_CN.js', language: 'zh_CN', skin_url: '/static/tinymce/skins/ui/oxide', // skin路径 height: 300, // 编辑器高度 branding: false, // 是否禁用“Powered by TinyMCE” menubar: true, // 顶部菜单栏显示 plugins: this.plugins, toolbar: this.toolbar,}同时在 mounted 中也需要初始化一次:
mounted (){tinymce.init({});},如果在这里传入上面的 init 对象,并不能生效,但什么参数都不传也会报错,所以这里传入一个空对象
https://blog.csdn.net/zjiang1994/article/details/79880806
https://blog.csdn.net/zjiang1994/article/details/79856058
完成了上面的初始化之后,就已经能正常运行编辑器了,但只有一些基本功能
tinymce 通过添加插件 plugins 的方式来添加功能
比如要添加一个上传图片的功能,就需要用到 image 插件,添加超链接需要用到 link 插件
<template> <p class='tinymce'> <h1>tinymce</h1> <editor id='tinymce' v-model='tinymceHtml' :init='init'></editor> <p v-html='tinymceHtml'></p> </p></template><script>import tinymce from "tinymce/tinymce";import "tinymce/themes/silver/theme";import Editor from "@tinymce/tinymce-vue";import "tinymce/icons/default/icons";import "tinymce/plugins/media"; // 插入视频插件import "tinymce/plugins/image";import "tinymce/plugins/link";import "tinymce/plugins/code";import "tinymce/plugins/table";import "tinymce/plugins/lists";import "tinymce/plugins/contextmenu";import "tinymce/plugins/wordcount";import "tinymce/plugins/colorpicker";import "tinymce/plugins/textcolor"; export default { name: 'tinymce', data () { return { tinymceHtml: '请输入内容', init: { language_url: '/static/tinymce/zh_CN.js', language: 'zh_CN', skin_url: '/static/tinymce/skins/ui/oxide', // skin路径 content_css:'/static/tinymce/skins/content/default/content.css', height: 300, // 编辑器高度 branding: false, // 是否禁用“Powered by TinyMCE” menubar: true, // 顶部菜单栏显示 font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif', fontsize_formats:'12px 14px 16px 18px 20px 22px 24px 26px 28px 30px 32px 34px 36px 38px 40px 50px 60px 70px 80px 90px 100px 120px 140px 160px 180px 200px', plugins: 'link lists image code table colorpicker textcolor wordcount contextmenu', toolbar:'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat', } } }, mounted () { tinymce.init({}) }, components: {Editor}}</script>但是当富文本在某一个弹窗上使用时, 工具栏会出现下拉选择时的层级比弹窗的小,所以,选项会被弹窗遮挡。 而解决这个问题,需要把工具栏的下拉框的层级提高, 找到static/tinymce/skins/ui/oxide/skin.min.css文件 把class名为tox-tinymce-aux的第一个的z-index属性变大即可
tinymce 提供了 images_upload_url 等 api 让用户配置上传图片的相关参数
但为了在不麻烦后端的前提下适配自家的项目,还是得用 images_upload_handler 来自定义一个上传方法
images_upload_handler: (blobInfo, success, failure) => { // const img = 'data:image/jpeg;base64,' + blobInfo.base64(); // success(img); this.handleImgUpload(blobInfo, success, failure); }这个方法会提供三个参数:blobInfo, success, failure
其中 blobinfo 是一个对象,包含上传文件的信息
success 和 failure 是函数,上传成功的时候向 success 传入一个图片地址,失败的时候向 failure 传入报错信息
handleImgUpload (blobInfo, success, failure) { // 上传的文件信息 let fd = new FormData(); fd.append("file", blobInfo.blob()); fd.append("type","tinymec") this.$http({ url: this.$http.adornUrl( "/localUpload/uploadForType" ), method: "post", data: fd, headers: { "Content-Type": "multipart/form-data;boundary=" + new Date().getTime(), "token": this.$cookie.get('token') }, }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: data.path + ",操作成功", type: "success", duration: 1500, onClose: () => { success(data.path) }, }); } else { failure('error') } });}<template> <Editor v-model="editHtml" :init="editorInit" @change="changeEdit" ></Editor></template><script>import tinymce from "tinymce/tinymce";import "tinymce/themes/silver/theme";import Editor from "@tinymce/tinymce-vue";import "tinymce/icons/default/icons";import "tinymce/plugins/media"; // 插入视频插件import "tinymce/plugins/image";import "tinymce/plugins/link";import "tinymce/plugins/code";import "tinymce/plugins/table";import "tinymce/plugins/lists";import "tinymce/plugins/contextmenu";import "tinymce/plugins/wordcount";import "tinymce/plugins/colorpicker";import "tinymce/plugins/textcolor";export default { props: { value: { //父组件传进来的默认值 default: "", }, }, components: { Editor }, Myeditmounted() { tinymce.init({}); }, created() {}, data() { return { editHtml: "", editorInit: { language_url: "/static/tinymce/zh_CN.js", language: "zh_CN", skin_url: "/static/tinymce/skins/ui/oxide", // skin路径 content_css: "/static/tinymce/skins/content/default/content.css", height: 300, // 编辑器高度 branding: false, // 是否禁用“Powered by TinyMCE” menubar: true, // 顶部菜单栏显示 font_formats: "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif", fontsize_formats: "12px 14px 16px 18px 20px 22px 24px 26px 28px 30px 32px 34px 36px 38px 40px 50px 60px 70px 80px 90px 100px 120px 140px 160px 180px 200px", plugins: "link lists image code table colorpicker textcolor wordcount contextmenu", toolbar: "bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat", images_upload_handler: (blobInfo, success, failure) => { // const img = "data:image/jpeg;base64," + blobInfo.base64(); // success(img); this.handleImgUpload(blobInfo, success, failure); }, }, }; }, watch: { value: { //data改变的时候同步到子组件 deep: true, handler(value) { this.editHtml = value; // console.log(value); }, }, editHtml: { //data改变的时候同步到子组件 deep: true, handler(val) { this.$emit('update:value', val); console.log(val); // console.log(this.value); }, }, }, methods: { handleImgUpload (blobInfo, success, failure) { // 上传的文件信息 let fd = new FormData(); fd.append("file", blobInfo.blob()); fd.append("type","tinymec") this.$http({ url: this.$http.adornUrl( "/file/uploadForType" ), method: "post", data: fd, headers: { "Content-Type": "multipart/form-data;boundary=" + new Date().getTime(), "token": this.$cookie.get('token') }, }).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: data.path + ",操作成功", type: "success", duration: 1500, onClose: () => { success(data.path) }, }); } else { failure('error') } });}, changeEdit(){ console.log(1111); }, },};</script><style></style><custom1> This could be e.g. documentation for the component.</custom1>155091.html