vue+tinymce

1.安装tinymce

 npm install tinymce -S

2.安装tinymce-vue

npm install @tinymce/tinymce-vue -S

3.下载中文语言包

地址:<https://www.tiny.cloud/get-tiny/language-packages/>

4.下载完后放到静态文件public目录下

 在public目录下新建tinymce,将上面下载的语言包解压到该目录
 在node_modules里面找到tinymce,将skins目录复制到public/tinymce里面

4.tinymce使用    封装成组件

在项目src -->components -->common 目录里添加tinymce.vue

内容如下(可根据自己项目需求更改)

<template>
<div class="tinymce-box">
<editor v-model="myValue" :init="init" :disabled="disabled" @onClick="onClick" ></editor>
</div>
</template>

<script>
import tinymce from 'tinymce/tinymce' //tinymce默认hidden,不引入不显示
import editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver/theme'
// 编辑器插件plugins
// 更多插件参考:https://www.tiny.cloud/docs/plugins/
import 'tinymce/plugins/image' // 插入上传图片插件
import 'tinymce/plugins/media' // 插入视频插件
import 'tinymce/plugins/table' // 插入表格插件
import 'tinymce/plugins/lists' // 列表插件
import 'tinymce/plugins/wordcount' // 字数统计插件
import 'tinymce/icons/default/icons.min.js'
import 'tinymce/plugins/paste'//张贴图片
export default {
components: {
editor
},
name: 'tinymce',
props: {
value: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
plugins: {
type: [String, Array],
default: 'lists image media table wordcount paste fontsizeselect forecolor'
},
toolbar: {
type: [String, Array],
default(){
['undo redo | bold italic| alignleft aligncenter alignright alignjustify |',
' fontsizeselect forecolor|image media ']
}
}
},
//[ 'undo redo | bold italic fontsizeselect forecolor| alignleft aligncenter alignright alignjustify |','image media '],
data() {
return {
init: {
language_url: '/tinymce/langs/zh_CN.js',
language: 'zh_CN',
skin_url: '/tinymce/skins/ui/oxide',
// skin_url: 'tinymce/skins/ui/oxide-dark',//暗色系
height: 650,
750,
font_formats:'微软雅黑=Microsoft YaHei,Helvetica Neue;PingFang SC;sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun;serifsans-serif;Terminal=terminal;monaco;Times New Roman=times new roman;times', //字体
color_cols: 7,
custom_colors: false,
color_map: [
"000000", "Black",
"BBFFFF", "PaleTurquoise1",
"00868B", "Turquoise4",
"458B74", "Aquamarine4",
"43CD80", "SeaGreen3",
"EEB4B4", "Green2",
"333399", "RosyBrown2",
"EE6363", "IndianRed2",
"EE2C2C", "Firebrick2",
"8B1A1A", "Firebrick4",
"CD0000", "Red3",
"4F4F4F", "grey31",
"B5B5B5", "grey71",
"008B8B", "DarkCyan",
"43CD80", "SeaGreen3",
"009ACD", "DeepSkyBlue3",
"0000FF", "Blue1",
"FFFF00", "Yellow",
"FF8247", "Sienna1",
],
plugins:'lists image media table wordcount paste fontsizeselect forecolor',
toolbar:[ 'undo redo | bold italic |fontsizeselect forecolor| alignleft aligncenter alignright alignjustify |','image|paste pastetext'],
branding: false,
menubar: false,
paste_data_images: true, // 设置为“true”将允许粘贴图像,而将其设置为“false”将不允许粘贴图像
// 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
// 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
images_upload_handler: (blobInfo, success, failure) => {
console.log(failure)
/* const img = 'data:image/jpeg;base64,' + blobInfo.base64()
success(img) */
// 图片异步上传处理函数
var formData = new FormData();
formData.append('file',blobInfo.blob());
// formData.append('group','editor');
// _this.$requestPost这个是我调用后台图片上传接口
console.log(blobInfo.blob())
this.axios({
url:'/upload',
method:'post',
token:true,
data:formData,
}).then(res=>{
this.$message.error(res.data.msg);
success(res.data.data.url)
})
},
setup: (ed) => {
const vm = this
ed.on('keyup', function (e) {
vm.wordLimit(e)
});
ed.on('input', function (e) {
vm.wordLimit(e)
})
ed.on('compositionstart', function (e) {
console.log(e)
vm.isChinese = false
});
ed.on('compositionend', function (e) {
console.log(e)
vm.isChinese = true
})
},
init_instance_callback: (editor) => {
// 注册事件
editor.on('paste', (e) => {
var ifra = document.getElementById("tinymces_ifr");
e.preventDefault();
var contentOnBlur = (e.originalEvent || e).clipboardData.getData('text/plain');
contentOnBlur = contentOnBlur.replace(/(<([^>]+)>)/ig, '');
if (!(20000 - e.target.innerText.length) && !this.limitNum) {
this.$message.error('超过最长保存字符')
this.limitNum++
}
ifra.contentWindow.document.execCommand('insertText', true, contentOnBlur.slice(0, 1000 - e.target.innerText.length));
});
},

},
myValue: this.value
}
},
mounted() {
tinymce.init({})
},
methods: {
// 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
// 需要什么事件可以自己增加
onClick(e) {
this.$emit('onClick', e, tinymce)
},
// 可以添加一些自己的自定义事件,如清空内容
clear() {
this.myValue = ''
},
//字数限制
wordLimit (e) {
const vm = this
let last = ''
let lastIndex = ''
let startVal = ''
let endVal = ''
if (e.target.innerText.length === 20000) {
vm.htmlText = e.target.innerHTML
//兼容输入法有可能会跳过1000
} else if ((!vm.isChinese && e.target.innerText.length === 200001)) {
last = e.target.innerText.substr(e.target.innerText.length - 1, 1)
lastIndex = e.target.innerHTML.lastIndexOf(last)
startVal = e.target.innerHTML.substring(0, lastIndex)
endVal = e.target.innerHTML.substring(lastIndex + 1, e.target.innerHTML.length)
vm.htmlText = startVal + endVal
}
if (e.target.innerText.length > 20000) {
e.target.innerHTML = vm.htmlText
/* var ifra = document.getElementById("tiny_ifr");
this.keepLastIndex(ifra.contentWindow.document.getElementById('tinymce'), ifra.contentWindow) */
if (!this.limitNum) {
this.$message.error('超过最长保存字符')
this.limitNum++
}
}
},
},
watch: {
value(newValue) {
this.myValue = newValue
},
myValue(newValue) {
this.$emit('input', newValue)
}
}
}
</script>
<style scoped>
/* .tox-tinymce{
600px;
height: 600px;
} */
</style>

原文地址:https://www.cnblogs.com/liuyuanchen/p/14692534.html