提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
根据公司业务的需要,后台管理系统需要换掉现有的富文本编辑器UEditor,还需要增加图片上传功能,我一轮搜索之后,发现现在更多人使用的是TinyMCE、Quill、WangEditor还有tiptap。我根据自己的需要以及网上的教程的可读性,选择了TinyMCE,公司使用的是Vue3。
官方文档:官方文档
中文文档: 中文文档
参考视频:b站参考视频
一、先把编辑器「搞到手」
最懒人的办法 —— 用 CDN
直接在网页里加一行代码,就像借别人的工具用,不用自己下载。
比如在 HTML 里塞这行:
<script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.js"></script>
注意哦,这里的no-api-key是演示用的,正式项目得去官网申请个 API Key,不然可能有功能限制。
程序员常用招 ——NPM 安装
如果你用的是 Vue、React 这些框架,直接在命令行敲一句:
npm install tinymce
装完之后在项目里引入,比如 Vue 里可能需要在组件里import tinymce from ‘tinymce’,然后初始化。
断网也能用 —— 下载离线包
去 TinyMCE 官网下载压缩包,解压到项目里,比如放在static/tinymce文件夹,然后引用路径写成./static/tinymce/tinymce.min.js。
二、让编辑器「显形」—— 初始化配置
首先得在 HTML 里给编辑器留个「座位」,比如一个div或者textarea:
<div id="my-editor"></div>
<!-- 或者用文本域 -->
<textarea id="my-editor"></textarea>
然后用 JavaScript 激活它,核心是tinymce.init()这个方法,至少得告诉它「绑定到哪个元素」:
tinymce.init({
selector: '#my-editor' // 这里写你HTML里的那个id,就像给编辑器贴标签
});
写完这两步,刷新页面,你会看到一个带工具栏的编辑器框框,搞定!
三、常用操作:怎么「搞内容」
获取编辑好的内容
如果页面只有一个编辑器,直接喊「活跃编辑器」:
const content = tinyMCE.activeEditor.getContent();
console.log(content); // 这里能看到HTML代码
如果有多个编辑器,得指定序号,比如第一个编辑器是0,第二个是1:
const firstEditor = tinyMCE.editors[0];
const content = firstEditor.getContent();
往编辑器里塞内容
tinyMCE.activeEditor.setContent("Hello, TinyMCE! 这里可以写HTML哦~");
只要纯文本,不要 HTML 标签
有时候需要提取编辑器里的文字,不要图片、链接这些标签:
const plainText = tinyMCE.activeEditor.getContent({ format: 'text' });
// 比如编辑器里有<p>你好</p>,这里会变成「你好」
四、「打扮」编辑器 —— 常用配置
换成中文界面
加一行language: ‘zh-CN’,但记得提前下载中文语言包,或者用 CDN 引入:
tinymce.init({
selector: '#my-editor',
language: 'zh_CN', // 注意下划线哦
// 语言包路径,如果CDN的话可能不用写,本地需要指定
language_url: '/static/tinymce/langs/zh_CN.js'
});
调整编辑器高度
比如想让它高一点:
tinymce.init({
selector: '#my-editor',
height: 400 // 单位是像素,也可以写'60vh'(视口高度的60%)
});
只看不编辑 —— 只读模式
给别人预览的时候用:
tinymce.init({
selector: '#my-editor',
readonly: true // 加上这个,编辑器就不能打字啦
});
自定义工具栏按钮
编辑器默认有很多按钮,你可以按需删减,比如只留加粗、斜体、链接:
tinymce.init({
selector: '#my-editor',
toolbar: 'bold italic link | alignleft aligncenter alignright'
// 用|分隔分组,比如这里分成了两组
});
加插件 —— 解锁新功能
比如想支持上传图片、插入表格,得先加载对应的插件,然后加到工具栏:
tinymce.init({
selector: '#my-editor',
plugins: 'image table link', // 插件名用空格隔开
toolbar: 'image table link' // 把插件对应的按钮加到工具栏
});
常用插件推荐:image(图片上传)、table(表格)、media(嵌入视频)、code(显示代码)。
五、「监听」编辑器 —— 事件处理
比如想知道用户什么时候开始编辑,或者内容有没有变化,可以加监听:
tinymce.init({
selector: '#my-editor',
setup: function(editor) {
// 编辑器初始化完成时触发
editor.on('init', function() {
console.log('编辑器Ready啦!');
});
// 内容变化时触发,比如用户打字、粘贴
editor.on('change', function() {
console.log('用户改内容了!');
});
// 获得焦点时(点进去编辑)
editor.on('focus', function() {
console.log('用户开始编辑啦!');
});
}
});
六、踩坑提醒(新手常犯的错)
selector 写错:比如 HTML 里的 id 是editor,结果写成了#editorr,编辑器会「隐身」。
插件没加载:想用图片上传,结果没写plugins: ‘image’,按钮会消失。
语言包路径错:中文界面不显示,可能是language_url路径写错了,记得检查文件是否存在。
七、集成到项目中并实现图片上传功能
// 引入TinyMCE(根据你的项目结构调整路径)
import tinymce from 'tinymce/tinymce';
import 'tinymce/icons/default';
import 'tinymce/themes/silver';
import 'tinymce/plugins/image';
import 'tinymce/plugins/code';
import 'tinymce/plugins/table';
import 'tinymce/langs/zh_CN';
// 初始化编辑器
export const initTinyMCE = () => {
tinymce.init({
selector: '#mytiny',
statusbar: false,
menubar: true,
menu: {
file: { title: '文件', items: 'newdocument' },
edit: { title: '编辑', items: 'undo redo | cut copy paste pasttext | selectall' }
},
toolbar: "undo redo | styles | bold italic | fontfamily fontsize forecolor | image table",
skin: 'oxide-dark',
plugins: "image code table",
language: 'zh_CN',
width: 1200,
height: 600,
// 图片配置
image_title: true,
image_caption: true,
image_dimensions: false,
image_class_list: [
{title: '无', value: ''},
{title: '居中', value: 'center-image'},
{title: '右对齐', value: 'right-image'}
],
style_formats: [
{title: '居中图片', selector: 'img', classes: 'center-image'},
{title: '右对齐图片', selector: 'img', classes: 'right-image'}
],
// 图片处理
paste_data_images: true,
images_dataimg_filter: function(img) {
return img.hasAttribute('internal-blob');
},
// 图片上传处理 - 转换为Base64
images_upload_handler: function(blobInfo, success, failure) {
const file = blobInfo.blob();
// 图片验证
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (!allowedTypes.includes(file.type)) {
failure('仅支持JPG、PNG、GIF、WebP格式的图片');
return;
}
// 大小限制
if (file.size > 2 * 1024 * 1024) {
failure('图片大小不能超过2MB');
return;
}
// 显示上传中状态
const imgId = 'uploading-img-' + Date.now();
const imgHtml = `<img id="${imgId}" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt="上传中..." style="display:block;margin:0 auto;">`;
tinymce.activeEditor.insertContent(imgHtml);
// 转换为Base64
const reader = new FileReader();
reader.onloadend = function() {
const base64Data = reader.result.split(',')[1];
// 模拟上传延迟(实际无需)
setTimeout(() => {
// 替换上传中图片为实际图片
const imgEl = tinymce.activeEditor.dom.select(`#${imgId}`)[0];
if (imgEl) {
tinymce.activeEditor.dom.setAttrib(imgEl, 'src', `data:${file.type};base64,${base64Data}`);
tinymce.activeEditor.dom.setAttrib(imgEl, 'id', '');
tinymce.activeEditor.dom.setAttrib(imgEl, 'alt', '已上传图片');
}
success(`data:${file.type};base64,${base64Data}`);
}, 1000);
};
reader.onerror = function() {
failure('图片读取失败');
// 移除上传中图片
const imgEl = tinymce.activeEditor.dom.select(`#${imgId}`)[0];
if (imgEl) {
tinymce.activeEditor.dom.remove(imgEl);
}
};
reader.readAsDataURL(file);
},
// 自定义样式(可根据需要调整)
content_style: `
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
line-height: 1.6;
font-size: 16px;
color: #333;
}
.center-image {
display: block;
margin: 0 auto;
max-width: 100%;
}
.right-image {
float: right;
margin-left: 10px;
max-width: 50%;
}
`
});
};
// 导出获取编辑器内容的方法
export const getEditorContent = () => {
return tinymce.activeEditor.getContent();
};
// 导出设置编辑器内容的方法
export const setEditorContent = (content) => {
tinymce.activeEditor.setContent(content);
};
使用方法示例(Vue 组件)
vue
<template>
<div>
<div id="mytiny"></div>
<button @click="saveContent">保存内容</button>
</div>
</template>
<script>
import { initTinyMCE, getEditorContent } from './tinymce-config';
export default {
mounted() {
// 初始化编辑器
initTinyMCE();
},
methods: {
saveContent() {
const content = getEditorContent();
console.log('保存内容:', content);
// 这里可以将内容发送到服务器
}
}
}
</script>
总结
本文主要记录将后台管理系统富文本编辑器从 UEditor 更换为 TinyMCE 的过程,重点介绍其快速上手方法及图片上传功能实现,内容如下:
获取方式:CDN 引入、NPM 安装、离线包下载。
初始化:通过tinymce.init({selector: ‘#xxx’})绑定 HTML 元素。
内容操作:getContent()获取内容、setContent()设置内容、{format: ‘text’}提取纯文本。
配置优化:中文界面、高度设置、只读模式、自定义工具栏及插件(如image实现图片上传)。
事件监听:通过setup监听编辑器初始化、内容变化等事件。
避坑提示:检查 selector、插件加载、语言包路径等常见问题。
图片上传:利用images_upload_handler将图片转为 Base64,支持类型 / 大小限制、上传状态显示及自定义样式布局。