一 资源下载
tinymce 官方为vue项目提供了一个组件 tinymce-vue
npm install tinymce -S
我package.json文件里tinymce的版本是^4.8.5
安装之后,在 node_modules 中找到 tinymce/skins 目录,然后将 skins 目录拷贝到 static 目录下
// 如果是使用 vue-cli 3.x 构建的 typescript 项目,就放到 public 目录下,文中所有 static 目录相关都这样处理
tinymce 默认是英文界面,所以还需要下载一个中文语言包(记得搭梯子!搭梯子!搭梯子!)
下载中文语言包,附上地址中文包下载地址
然后将这个语言包放到 static 目录下,为了结构清晰,我包了一层 tinymce 目录
二 创建组件,在组件中引入以下文件
创建组件 tinymce-editor.vue
<template>
<textarea :id='id' :value='value'></textarea>
</template>
<script>
// Import TinyMCE
import store from '@/store/store'
import tinymce from 'tinymce/tinymce'
import 'tinymce/skins/lightgray/skin.min.css'
import 'tinymce/themes/modern/theme' //import 'tinymce/themes/silver/theme'
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/link'
import 'tinymce/plugins/image'
import 'tinymce/plugins/code'
import 'tinymce/plugins/table'
import 'tinymce/plugins/textcolor'
import 'tinymce/plugins/paste'
import 'tinymce/plugins/colorpicker'
const INIT = 0
const CHANGED = 2
export default {
data () {
return {
no: ''
}
},
props: {
value: {
type: String,
editor: null,
required: true
},
setting: {},
url: { // 接口
default: '',
type: String
},
accept: { // 文件类型
default: 'image/jpeg, image/png',
type: String
},
maxSize: { // 大小
default: 2097152,
type: Number
},
withCredentials: {
default: false,
type: Boolean
}
},
watch: {
value: function (val) {
console.log('init ' + val)
if (this.status === INIT || tinymce.activeEditor.getContent() !== val) {
tinymce.activeEditor.setContent(val)
}
this.status = CHANGED
}
},
data () {
return {
status: INIT,
id: 'editor-' + new Date().getMilliseconds()
}
},
methods: {
},
mounted () {
const _this = this
const setting =
{
selector: '#' + _this.id,
images_upload_url: 'http://localhost:8080/uploadCenter/upload/images',
language_url: '/tinymce/langs/zh_CN.js',
language: 'zh_CN',
init_instance_callback: function (editor) {
// EDITOR = editor
console.log('Editor: ' + editor.id + ' is now initialized.')
editor.on('input change undo redo', () => {
var content = editor.getContent()
_this.$emit('show', content)
})
},
content_style: `
* { padding:0; margin:0; }
html, body { height:100%; }
img { max-width:100%; display:block;height:auto; }
a { text-decoration: none; }
iframe { width: 100%; }
p { line-height:1.6; margin: 0px; }
table { word-wrap:break-word; word-break:break-all; max-width:100%; border:none; border-color:#999; }
.mce-object-iframe { width:100%; box-sizing:border-box; margin:0; padding:0; }
ul,ol { list-style-position:inside; }
`,
insert_button_items: 'image link | inserttable',
paste_retain_style_properties: 'all',
paste_word_valid_elements: '*[*]', // word需要它
paste_data_images: true, // 粘贴的同时能把内容里的图片自动上传,非常强力的功能
paste_convert_word_fake_lists: false, // 插入word文档需要该属性
paste_webkit_styles: 'all',
paste_merge_formats: true,
nonbreaking_force_tab: false,
paste_auto_cleanup_on_paste: false,
menubar: 'edit insert view format table tools',
branding: false,
plugins: [
'advlist autolink lists image charmap print preview hr anchor pagebreak imagetools',
'searchreplace visualblocks visualchars code fullpage',
'insertdatetime nonbreaking save table contextmenu directionality',
'emoticons paste textcolor colorpicker textpattern imagetools'
],
toolbar1: ' newnote print fullscreen preview | undo redo | insert | styleselect | forecolor backcolor bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image emoticons media codesample',
// 上传图片回调
images_upload_handler (blobInfo, success, failure) {
let xhr = ''
let formData = ''
xhr = new XMLHttpRequest()
xhr.withCredentials = false
xhr.open('POST', 'http://localhost:8080/uploadCenter/upload/images')
xhr.setRequestHeader('token','')
xhr.onload = () => {
let json = {}
if (xhr.status !== 200) {
failure('HTTP Error: ', xhr.status)
return
}
console.log(xhr)
json = JSON.parse(xhr.responseText)
console.log(json)
success(json.data.httpFilePath)
}
formData = new FormData()
formData.append('file', blobInfo.blob())
xhr.send(formData)
}
}
Object.assign(setting, _this.setting)
tinymce.init(setting)
},
beforeDestroy: function () {
tinymce.get(this.id).destroy()
}
}
</script>
三 其他组件引用
<template>
<div class="app-container calendar-list-container">
<div style="width: 100%;">
<editor class="editor" :value="content" :setting="editorSetting" @show="editors" :with-credentials="withCredentials"></editor>
</div>
</div>
</template>
<script>
import editor from './tinymce-editor' // 根据tinymce-editor.vue组件位置引入
export default {
data () {
return {
editorSetting: { // 配置富文本编辑器高
height: 500
},
withCredentials: true,
content: '', // 富文本编辑器双向绑定的内容
formLeft: {
title: ''
}
}
},
components: { // 引入组件
editor
},
methods: {
editors (content) { // editor组件传过来的值赋给content
console.log(content)
this.content = content
}
}
}
</script>