在Vue项目中使用tinymce富文本编辑器
TinyMC编辑器简介
TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。跟其他富文本编辑器相比,有着丰富的插件,支持多种语言,能够满足日常的业务需求并且免费。
TinyMCE的优势:
开源可商用,基于LGPL2.1
插件丰富,自带插件基本涵盖日常所需功能
接口丰富,可扩展性强,有能力可以无限拓展功能
界面好看,符合现代审美
提供经典、内联、沉浸无干扰三种模式(详见“介绍与入门”)
对标准支持优秀(自v5开始)
多语言支持,官网可下载几十种语言。
下图为我开启全部功能的截图

TinyMCE中文文档地址:TinyMCE中文文档中文手册
1、安装
vue-cli版本:3.x+
安装tinymce
npm install tinymce@6.3 -S
安装tinymce-vue
npm install --save tinymce "@tinymce/tinymce-vue@^5"
这两个组件安装完之后,在public目录下新建文件夹tinymce,目录建好后,找到node_modules文件夹下的tinymce/skins目录,将skins目录复制到我们创建的tinymce文件夹内。
vue-cli版本:2.x
安装tinymce,我安装的是5.10.7
npm install tinymce@5.10.7 -S
安装tinymce-vue
npm install --save tinymce "@tinymce/tinymce-vue@^3"
安装之后,在 node_modules 中找到 tinymce/skins 目录,然后将 skins 目录拷贝到 public/tinymce 目录下
注意: 如果是使用 vue-cli 3.x 之前构建的 typescript 项目,就放到 static 目录下,和文中所有 public 目录一样处理
tinymce 默认是英文界面,所以还需要下载一个中文语言包
然后将这个语言包放到相同 public/tinymce 目录下新建的langs文件目录中
这个是vue-cli3项目的放法
2、配置中文语言
到官网下载中文语言包 zh_CN.js
在刚才创建的static/tinymce文件夹内再新建langs文件夹,用来存放我们下载的中文语言包,如下图所示

vue-cli2.x 同理
3.组件
<template><Editor id="tinymce" v-model="content" :init="init"></Editor>
</template><script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver/theme";
import "tinymce/plugins/image";
import "tinymce/plugins/link";
import "tinymce/plugins/code";
import "tinymce/plugins/table";
import "tinymce/plugins/lists";
import "tinymce/plugins/wordcount";
import "tinymce/icons/default/icons";
import "tinymce/themes/silver";
import "tinymce/plugins/media";
import "tinymce/plugins/contextmenu";
import "tinymce/plugins/colorpicker";
import "tinymce/plugins/textcolor";
import "tinymce/plugins/preview";
import "tinymce/plugins/advlist";
import "tinymce/plugins/codesample";
import "tinymce/plugins/hr";
import "tinymce/plugins/fullscreen";
import "tinymce/plugins/textpattern";
import "tinymce/plugins/searchreplace";
import "tinymce/plugins/autolink";
import "tinymce/plugins/directionality";
import "tinymce/plugins/visualblocks";
import "tinymce/plugins/visualchars";
import "tinymce/plugins/template";
import "tinymce/plugins/charmap";
import "tinymce/plugins/nonbreaking";
import "tinymce/plugins/insertdatetime";
import "tinymce/plugins/imagetools";
import "tinymce/plugins/autosave";
import "tinymce/plugins/autoresize";
import "tinymce/plugins/paste";
import "tinymce/plugins/print";
import "tinymce/plugins/quickbars";
import "tinymce/plugins/emoticons";
import "tinymce/plugins/bbcode";
import "tinymce/plugins/tabfocus";
// 扩展插件
// import "/tinymce/plugins/lineheight/plugin";
// import "/tinymce/plugins/bdmap/plugin";import { uploadImageFile, deleteFile } from "@/api/geekplus/articles";
export default {name: "TinyEditor",components: { Editor },props:{value: {type: String,default: "",},},data() {return {content: "",//fileList: [],allImageList: [],baseHost: window.location.host,baseApi: process.env.VUE_APP_BASE_API,init: {language_url: "/tinymce/langs/zh_CN.js", // 语言包位置,因为放在public下所以可以省略publicselector: "#tinymce", //tinymce的id// auto_focus: 'element1',language: "zh_CN", //语言类型skin_url: "/tinymce/skins/ui/oxide",height: 650, //编辑器高度min_height: 400,highlight_on_focus: true,// contextmenu_never_use_native: true,//5.0.1draggable_modal: true,//inline: true,// content_style: "p {margin: 2px 0;}",init_instance_callback: (editor) => {// 更改元素为Diveditor.execCommand('mceInsertContent', false, '<p></p>')},browser_spellcheck: true, // 拼写检查// elementpath: false, //禁用编辑器底部的状态栏// statusbar: false, // 隐藏编辑器底部的状态栏// paste_data_images: true, // 允许粘贴图像// menubar: false, //最顶部文字信息mobile: {menubar: true,plugins: ["autosave", "lists", "autolink"],toolbar: ["undo", "bold", "italic", "styleselect"],},// mode: "textareas",placeholder: "在此处书写...",// forced_root_block: '', // 删除在tinymce中自动添加的p标签// force_br_newlines : true,// force_p_newlines : false,preview_styles: "font-size color",invalid_styles: {'*': 'color font-size', //全局无效样式'a': 'background', // 链接禁用背景样式},plugins:"image link code codesample table lists wordcount autosave autolink insertdatetime preview media fullscreen quickbars print template", //就可以增加上面引入的插件,加入下面这一行就可以在toolbar栏显示相应插件。branding: false, //是否禁用“Powered by TinyMCE”toolbar: [{name: "history",items: ["undo", "redo"],},{name: "styles",items: ["styleselect"],},{name:'code',items:['codesample']},{name: "formatting",items: ["bold", "italic", "underline", "strikethrough"],},{name: "fonts",items: ["fontselect", "fontsizeselect", ],},{name: "colors",items: ["forecolor", "backcolor"],},{name: "media&link",items: ["link", "image", "media"],},{name: "alignment",items: ["alignleft", "aligncenter", "alignright", "alignjustify"],},{name: "indentation",items: ["outdent", "indent"],},{name: "blockquote",items: ["blockquote"],},{name: "table",items: ["table"],},{name: "lists",items: ["numlist", "bullist"],},{name: "tools",items: ["preview", 'print', "fullscreen"],},],//toolbar: "undo redo | fontselect fontsizeselect link autolink lineheight | forecolor backcolor | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | image imagetools | code | h1 h2 h3 h4 h5 blockquote table numlist bullist outdent indent preview fullscreen", //工具栏// toolbar_groups: {// formatting: {// icon: 'bold',// tooltip: 'Formatting',// items: 'bold italic underline | superscript subscript'// }// },toolbar_mode: "sliding",//toolbar_sticky: true,image_caption: true,images_upload_handler: (blobInfo, success, failure, progress) => {this.uploadFile(blobInfo, success, failure);},//file_picker_callback: "",fontsize_formats:"8px 10px 12px 14px 16px 18px 24px 36px 48px 56px 72px",font_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;",// lineheight_formats: '1 1.1 1.2 1.3 1.4 1.5 2',// link_list: [// { title: '预置链接1', value: 'http://www.tinymce.com' },// { title: '预置链接2', value: 'http://tinymce.ax-z.cn' }// ],// image_list: [// { title: '预置图片1', value: 'https://www.tiny.cloud/images/glyph-tinymce@2x.png' },// { title: '预置图片2', value: 'https://www.baidu.com/img/bd_logo1.png' }// ],// image_class_list: [// { title: 'None', value: '' }// // { title: 'Some class', value: 'class-name' }// ],tabfocus_elements: "tinymce",importcss_append: true,textpattern_patterns: [{ start: "*", end: "*", format: "italic" },{ start: "**", end: "**", format: "bold" },{ start: "#", format: "h1" },{ start: "##", format: "h2" },{ start: "###", format: "h3" },{ start: "####", format: "h4" },{ start: "#####", format: "h5" },{ start: "######", format: "h6" },{ start: "1. ", cmd: "InsertOrderedList" },{ start: "* ", cmd: "InsertUnorderedList" },{ start: "- ", cmd: "InsertUnorderedList" },],setup: (editor) => {// 自定义toolbar按钮,需要在toolbar添加editor.ui.registry.addButton('testBtn', {text: `按钮文字`,tooltip: '按钮提示',onAction: () => editor.insertContent('<a href="https://www.geekplus.xyz" target="_blank">test text</a>')})},},};},// init: {// setup: (Editor) => {// // 初次化编辑器// Editor.on("init", () => {// Editor.setContent(this.value);// });// },// },watch: {value(newVal) {//this.content = newValue;//用户vue绑定回显//if (this.isInit) {//this.isInit = false;//this.getContent();// this.$nextTick(() => {// const editor = tinymce.get("tinymce");// editor.activeEditor.getContent()// editor.setContent(newVal);// });//}this.content=newVal;},content(newValue) {this.$emit("input", newValue);console.log(newValue);}},//获取焦点光标到最后面keepLastIndex (obj, window) {if (window.getSelection) { //ie11 10 9 ff safariobj.focus(); //解决ff不获取焦点无法定位问题var range = window.getSelection(); //创建rangerange.selectAllChildren(obj); //range 选择obj下所有子内容range.collapseToEnd(); //光标移至最后} else if (document.selection) { //ie10 9 8 7 6 5var range = document.selection.createRange(); //创建选择对象range.moveToElementText(obj); //range定位到objrange.collapse(false); //光标移至最后range.select();}}mounted() {tinymce.init({});this.$nextTick(() => {var ifra = document.getElementById("tinymce_ifr");// this.keepLastIndex(// ifra.contentWindow.document.getElementById("tinymce")// );});},methods: {// file_picker_callback: function(callback, value, meta) {// // Provide file and text for the link dialog// if (meta.filetype == 'file') {// callback('mypage.html', {text: 'My text'});// }// // Provide image and alt text for the image dialog// if (meta.filetype == 'image') {// callback('myimage.jpg', {alt: 'My alt text'});// }// // Provide alternative source and posted for the media dialog// if (meta.filetype == 'media') {// callback('movie.mp4', {source2: 'alt.ogg', poster: 'image.jpg'});// }// },getContent(){var cnt = tinymce.editors['tinymce'].getContent();//console.log(cnt);},//自定义上传函数uploadFile(blobInfo, success, failure, progress) {let formData = new FormData();formData.append("file", blobInfo.blob());uploadImageFile(formData).then((response) => {//console.log(response);var serverUrl = response.url;let uploadSuccess = {};const imageUrl ="https://www.geekplus.xyz" + this.baseApi + serverUrl;// this.$message({// message: "上传" + response.msg,// type: "success",// });//success函数获取我们反悔的图片url,就实现了插入编辑器了success(imageUrl);// this.content += urluploadSuccess = { filePath: serverUrl };this.allImageList.push(uploadSuccess);}).catch((error) => {//console.log(error);failure("Invalid JSON: " + error.msg);this.$message({message: error.msg,type: "error",showClose: true,});});},},destroyed() {},
};
</script>
<style>
</style>
4.组件使用
<tiny-editor v-model="form.articleContent" @onSelectionChange="onEditorBlur($event)">
</tiny-editor>
import TinyEditor from "@/components/TinyMCE"
components: { TinyEditor },相关文章:
在Vue项目中使用tinymce富文本编辑器
TinyMC编辑器简介 TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。跟其他富文本编辑器相比,有着丰富的插件,支持多种语言,能够满足日常的业务需求并且免费。 TinyMCE的优势: 开源可商用,基于LGPL2.1 插…...
GPT-4 和ChatGPT API的定价分析
OpenAI发布了他们的ChatGPT新机器学习模型GPT-4。GPT-4是GPT-3的一大进步,GPT-3是当前ChatGPT免费版本(GPT 3.5 Turbo)所运行的模型的基础,今天我们也来凑个热点,研究一下它们的定价 GPT-4新的功能 GPT-4可以在对话中使用图像,并…...
基于html+css的盒子展示2
准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…...
【持续更新篇】SLAM视觉特征点汇总+ORB特征点+VINS前端
Harris角点 opencv函数 cornerHarris提取输入图像的Harris角点 检测原理 检测思想:使用一个固定窗口在图像上进行任意方向的滑动,对比滑动前后的窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有较大灰度变化…...
【C语言】初阶指针(指针及其类型以及野指针)
简单不先于复杂,而是在复杂之后。 目录 1. 指针是什么? 2. 指针和指针类型 2.1 指针-整数 2.2 指针的解引用 3. 野指针 3.1 野指针成因 3.2 如何规避野指针 1. 指针是什么? 指针理解的两个要点: 1. 指针是内存中最小…...
UDS统一诊断服务【六】访问时序参数0X83服务
文章目录前言一、访问时序参数服务介绍二、数据格式2.1 请求报文2.2 子功能2.3 响应三、举例前言 本文介绍UDS统一诊断服务的访问时序参数0X83服务,希望能对你有所帮助 一、访问时序参数服务介绍 这个服务我目前在项目中没怎么用到过,先来看看ISO14229…...
Linux应用编程(文件属性与目录)
本章将会讨论如下主题内容。 ⚫ Linux 系统的文件类型; ⚫ stat 系统调用; ⚫ 文件各种属性介绍:文件属主、访问权限、时间戳; ⚫ 符号链接与硬链接; ⚫ 目录; ⚫ 删除文件与文件重命名。 一、Linux 系统中…...
第十四届蓝桥杯嵌入式详解
目录 第一部分 客观试题(15 分) 不定项选择(1.5 分/题) 第二部分 程序设计试题(85 分) 2.1 STM32CubeMX初始化配置 2.1.1 配置GPIO 2.1.2 配置ADC 2.1.3 配置RCC 2.1.4 配置定时器TIM 2.1.5 配置ADC1、AD…...
新建论文三线表模板,一键格式刷
论文三线表模板写在最前面①表设计,新建表格样式②三线表上下线③三线表标题线④设置表格居中⑤设置表头格式容易出错的步骤写在最前面 论文写完啦,准备调整格式 之前建模也是三线表,但只能基于该文档模板,所以重新设置一下。 如…...
攻防世界-web2(逆向加密算法)
打开链接是PHP源码 给了一串密文,并对这串密文进行了一系列操作加密,注释里说解密$miwen就是flag 在此我们先介绍一些PHP内置函数: strrev(string): 反转字符串 strlen(string): 返回字符串的长度 substr(string, start, length): 返回字符…...
C语言学习1--------Visual Studio集成开发环境的搭建
C语言学习1--------Visual Studio集成开发环境的搭建适合初学者适用集成开发环境下载 Visual Studio 2019安装 Visual Studio 2019安装工作负载为C自定义安装位置激活 Visual Studio适合初学者适用集成开发环境 建议初学者适用最新的——Visual Studio 2019为集成开发环境。 部…...
腾讯云轻量应用服务器搭建网站教程(WordPress为例)
腾讯云轻量应用服务器搭建WordPress网站教程,先安装WordPress应用镜像,然后远程连接轻量应用服务器获取WP用户名和密码,域名DNS解析到轻量服务器IP地址,登陆WordPress后台管理全过程,腾讯云百科来详细说下腾讯云轻量服…...
mac上的PCB设计软件现状
Altium Designer是一款商业化的电路板设计软件,目前没有Mac版本。但是,MacOS上有一些类似Altium Designer的电路板设计软件,以下是一些常用的软件: Eagle:Eagle是一款商业化的电路板设计软件,具有强大的功能…...
【面试题】JavaScript 你常用的 函数有哪些呢? (12个)
大厂面试题分享 面试题库 前后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 web前端面试题库 VS java后端面试题库大全 本文收集了 12 个在日常开发中非常常用的函数,有些可能很复杂,有些可…...
Java集合——Set接口学习总结
一、HashSet实现类 1.常用方法 增加:add(E e)删除:remove(Object o)、clear()修改:查看:iterator()判断:contains(Object o)、isEmpty()常用遍历方式:Set<String> set new HashSet<String>()…...
2023最全的自动化测试入门基础知识(建议收藏)
1)首先,什么是自动化测试? 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。通常,在设计了测试用例并通过评审之后,由测试人员根据测试用例中描述的过程一步步执行测试,得到实际结果与期望结果的比较。…...
【RabbitMQ】SpringBoot整合RabbitMQ、实现RabbitMQ五大工作模式(万字长文)
目录 一、准备 1、创建SpringBoot项目 2、添加配置信息 3、创建配置类 二、RabbitMQ的配置类里创建队列 三、RabbitMQ的配置类里创建交换机及绑定队列 四、SpringBoot整合RabbitMQ入门案例 1、生产者 2、消费者 四、SpringBoot里实现RabbitMQ五大工作模式 1、简单模式…...
ES6(函数扩展、数组扩展)
一、 函数扩展 1. 参数可以默认 ES5调用函数:如果给参数设置默认需要进行判断 ES6可以直接给参数设置默认 //ES5 function log(x, y) {//两种判断方法(传统分支判断、利用逻辑符)if (typeof y undefined) {y World;}//y y || World;cons…...
postman汉化教程
文章目录1. 下载对应版本的postman2.下载对应版本的汉化包2.1. github下载地址 : (9.12.2)2.2 百度网盘(9.12.2)3. 打开postman安装位置4. 压缩包解压到/resources目录下5. 重启postman即可汉化成中文了1. 下载对应版本的postman …...
java day8
第8章 数据结构8.1 超越数组8.2 java数据结构8.2.1 Iterator8.2.2 位组8.2.3 链表8.2.4 遍历数据结构8.2.5 堆栈8.1 超越数组 java类库的java.util包中有一组数据结构,它们让您能够更灵活地组织和操纵数据。 8.2 java数据结构 8.2.1 Iterator 接口Iterator提供了…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
