TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有:UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。
TinyMCE的优势:
tinyMCE中文文档
npm install tinymce @tinymce/tinymce-vue -S
然后把node_modules/tinymec下的skins文件夹复制到public文件夹下
最后下载语言包,把里面的zh_CN.js也放进
中文包下载地址
//TEditor.vue
<template>
<editor v-model="content" tag-name="div" :init="init" />
</template>
<script lang="ts">
import { upload } from "../api/upload";
import tinymce from "tinymce/tinymce";
import Editor from "@tinymce/tinymce-vue";
//根据需要引入
import "tinymce/themes/silver/theme"; // 引用主题文件
import "tinymce/icons/default"; // 引用图标文件
import "tinymce/plugins/link";
import "tinymce/plugins/code";
import "tinymce/plugins/table";//插入表格
import "tinymce/plugins/autoresize";
import "tinymce/plugins/autosave";
import "tinymce/plugins/charmap"; //特殊字符
import "tinymce/plugins/code"; //查看源码
import "tinymce/plugins/codesample"; //插入代码1
import "tinymce/plugins/directionality"; //
import "tinymce/plugins/fullscreen"; //全屏
import "tinymce/plugins/image"; //图片
import "tinymce/plugins/imagetools"; //图片工具
import "tinymce/plugins/importcss"; //图片工具
import "tinymce/plugins/media"; //媒体插入
import "tinymce/plugins/preview"; //预览
import "tinymce/plugins/quickbars"; //快捷菜单
import "tinymce/plugins/searchreplace"; //查询替换
import "tinymce/plugins/tabfocus"; //
import "tinymce/plugins/textpattern"; //
import { onMounted, ref, watch } from "vue";
export default {
props: ["modelValue"],
components: {
editor: Editor,
},
emits: { "update:modelValue": null },
setup(props: any, context: any) {
const init = {
language_url: "/public/tinymce/langs/zh_CN.js", // 中文语言包路径
language: "zh_CN",
skin_url: "/public/tinymce/skins/ui/oxide", // skin路径
content_css: "/public/tinymce/skins/content/default/content.css", //以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入
menubar: false, // 隐藏菜单栏
autoresize_bottom_margin: 50,
max_height: 500,
min_height: 350,
// height: 320,
toolbar_mode: "none",
plugins:
"textpattern tabfocus searchreplace quickbars preview media importcss imagetools image fullscreen directionality codesample code charmap link code table autoresize autosave link", // 插件需要import进来
toolbar:
"formats undo redo fontsizeselect fontselect searchreplace preview pagebreak media image|outdent indent aligncenter alignleft alignright alignjustify lineheight underline quicklink h2 h3 blockquote numlist bullist table removeformat forecolor backcolor bold italic strikethrough charmap link codesample code preview fullscreen",//工具栏展示的
content_style: "p {margin: 5px 0; font-size: 14px}",
fontsize_formats: "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;",
branding: false,
elementpath: false,
resize: false, // 禁止改变大小
statusbar: false, // 隐藏底部状态栏
// paste_data_images: true, // 允许粘贴图像
file_picker_types: "file image media",
//文件上传
file_picker_callback: function (callback: any, value: any, meta: any) {
//文件分类
var filetype =
".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4";
//为不同插件指定文件类型
switch (meta.filetype) {
case "image":
filetype = ".jpg, .jpeg, .png, .gif";
break;
case "media":
filetype = ".mp3, .mp4";
break;
case "file":
default:
}
//模拟出一个input用于添加本地文件
var input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", filetype);
input.click();
input.onchange = function (v: any) {
var file = v.target.files[0];
var formData = new FormData();
formData.append("file", file, file.name);
upload(formData).then((res) => {
callback(res.file.url, { title: file.name });
});
};
},
// 图片上传
images_upload_handler: async (blobInfo: any, success: any) => {
//官网写法,返回的图片路径为base64
// var reader = new FileReader();
// reader.readAsDataURL(blobInfo.blob());
// reader.onload = function () {
// success(this.result);
// };
//改写,通过自己的upload接口,返回的图片时正常的url格式
var form = new FormData();
form.append("file", blobInfo.blob(), blobInfo.filename());
upload(form).then((res) => {
success(res.file.url);
});
},
};
const content = ref();
onMounted(() => {
content.value = props.modelValue;
});
watch(
() => content.value,
() => {
revert_data(content.value);
}
);
tinymce.init; // 初始化
const revert_data = (content: any) => {
//实现数据的双向绑定
context.emit("update:modelValue", content);
};
return {
init,
revert_data,
content,
};
},
};
</script>
使用组件
<template>
<div>
<TEditor ref="editor" v-model="state.content" />
</div>
</template>
<script setup>
import { reactive,watch} from 'vue'
import TEditor from "@/components/TEditor.vue";
</script>
<style lang="scss" scoped>
state=reactive({
content:"",//获取TEditor的内容
})
watch(()=>state.content,()=>{
//监控TEditor内容的变化
console.log(state.content)
))
</style>