问题:
页面内a-drawer或者a-modal弹出VueTinymce后,首次不能输入,需要再次弹出才可以输入
解决:
组件:
<template>
<div class='vue-tinymce-wrapper' :id="selectorId">
<Editor v-model='newTinymceHtml' :init='init' @onBlur='getContent' v-if="!reloading"></Editor>
</div>
</template>
<script>
import axios from 'axios'
import tinymce from 'tinymce/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/plugins/advlist';
import 'tinymce/plugins/autolink';
import 'tinymce/plugins/charmap';
import 'tinymce/plugins/print';
import 'tinymce/plugins/preview';
import 'tinymce/plugins/hr';
import 'tinymce/plugins/anchor';
import 'tinymce/plugins/pagebreak';
import 'tinymce/plugins/lineheight';
import 'tinymce/plugins/searchreplace';
import 'tinymce/plugins/visualblocks';
import 'tinymce/plugins/visualchars';
import 'tinymce/plugins/fullscreen';
import 'tinymce/plugins/insertdatetime';
import 'tinymce/plugins/media';
import 'tinymce/plugins/nonbreaking';
import 'tinymce/plugins/directionality';
import 'tinymce/plugins/emoticons';
import 'tinymce/plugins/template';
import 'tinymce/plugins/paste';
import 'tinymce/plugins/emoticons/js/emojis';
import 'tinymce/skins/ui/oxide/skin.css'
import { zh_CN } from '@/assets/tinymce/lang/zh_CN'
import { upLoadImages } from '@/api/public';
import {
getVmParentByName
} from '@/utils/get'
export default {
name: 'VueTinymce',
data() {
return {
newTinymceHtml: this.tinymceHtml,
reloading: false,
selectorId: new Date().getTime(),
init: {
language_url: zh_CN,
language: 'zh_CN',
skin_url: './tinymce/skins/ui/oxide',
height: 600,
forced_root_block: 'p',
force_p_newlines: true,
paste_word_valid_elements: '*[*]', // word需要它
paste_data_images: true, // 粘贴的同时能把内容里的图片自动上传
paste_convert_word_fake_lists: false,
paste_webkit_styles: 'all',
paste_merge_formats: true,
nonbreaking_force_tab: false,
paste_auto_cleanup_on_paste: false,
fontsize_formats: '10px 11px 12px 13px 14px 16px 18px 20px 24px',
imagetools_toolbar:
'rotateleft rotateright | flipv fliph | editimage imageoptions',
content_style: `
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; }
`,
plugins: [
'advlist autolink link image lists charmap print preview hr anchor pagebreak lineheight',
'searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime nonbreaking',
'table directionality emoticons template paste'
],
toolbar:
'preview | bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist lineheight | outdent indent blockquote | undo redo | link image code',
branding: false,
images_upload_handler: this.imageUploadHandler,
file_picker_types: 'media',
file_picker_callback: this.mediaUploadHandler
}
};
},
props: {
tinymceHtml: {
default: '',
type: String
},
url: {
default: `/Index/upLoadImages`,
type: String
},
accept: {
default: 'image/jpeg, image/png',
type: String
},
maxSize: {
default: 2097152,
type: Number
},
withCredentials: {
default: false,
type: Boolean
},
},
watch: {
tinymceHtml(newValue) {
this.newTinymceHtml = (newValue == null ? '' : newValue)
},
newTinymceHtml(newValue) {
this.$emit('edit-content', newValue)
}
},
mounted() {
tinymce.init({});
this.initATabsChangeAutoReload()
},
methods: {
initATabsChangeAutoReload() {
// 获取父级
let modal = getVmParentByName(this,'ADrawer')
if(modal){
this.reload();
}
},
reload() {
this.reloading = true
this.$nextTick(() => this.reloading = false)
},
imageUploadHandler (blobInfo, success, failure) {
if (blobInfo.blob().size > this.maxSize) {
failure('文件体积过大')
}
if (this.accept.indexOf(blobInfo.blob().type) >= 0) {
new Promise(resolve => {
const params = new FormData()
params.append('images[]', blobInfo.blob());
params.append('type', this.uploadType);
upLoadImages(params).then((res) => {
resolve(res.res)
})
}).then(path => {
const a = new FormData() // 创建form对象
a.append('file', blobInfo.blob())
a.append('key', this.guid() + '.' + blobInfo.blob().name)
a.append('token', path)
axios.post('https://up-z2.qiniup.com', a).then(res => {
success(`https://xxxx,com/${res.data.key}`)
})
})
} else {
failure('图片格式错误');
}
},
guid () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
},
mediaUploadHandler (callback, value, meta) {
if (meta.filetype == 'media') {
let input = document.createElement('input') //创建一个隐藏的input
input.setAttribute('type', 'file')
let that = this
input.onchange = function () {
let file = this.files[0] // 选取第一个文件
}
//触发点击
input.click()
}
},
// 上传视频拿到url
uploadMedia(token, file, type) {},
getContent () {
this.$emit('edit-content', this.newTinymceHtml)
}
},
computed: {},
components: {
Editor
}
};
</script>
get.js
/** * 根据组件名获取父级 *
* @param vm * @param name * @returns {Vue | null|null|Vue} */
export function getVmParentByName(vm, name) {
let parent = vm.$parent
if (parent && parent.$options) {
if (parent.$options.name === name) {
return parent
} else {
let res = getVmParentByName(parent, name)
if (res) {
return res
}
}
}
return null
}
引用:
<Vue-tinymce
ref="tinymce"
@edit-content="getContent"
:tinymceHtml="content"
></Vue-tinymce>
getContent (richText) {
this.content = richText
},