在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下所以可以省略public
selector: "#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.1
draggable_modal: true,
//inline: true,
// content_style: "p {margin: 2px 0;}",
init_instance_callback: (editor) => {
// 更改元素为Div
editor.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 += url
uploadSuccess = { 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 },
更多推荐
所有评论(0)