Vue中如何使用tinymce富文本编辑器
12 index.vue<template><div:class="{ fullscreen: fullscreen }"class="tinymce-container":style="{ width: containerWidth }"><textarea :id="tinymceId" class="tinymce-textarea" /></div
1
2 index.vue
<template>
<div
:class="{ fullscreen: fullscreen }"
class="tinymce-container"
:style="{ width: containerWidth }"
>
<textarea :id="tinymceId" class="tinymce-textarea" />
</div>
</template>
<script>
/**
* docs:
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
*/
import plugins from "./plugins";
import toolbar from "./toolbar";
import load from "./dynamicLoadScript";
import vue from "vue";
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
const tinymceCDN =
"https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js";
export default {
name: "Tinymce",
props: {
id: {
type: String,
default: function () {
return (
"vue-tinymce-" +
+new Date() +
((Math.random() * 1000).toFixed(0) + "")
);
}
},
value: {
type: String,
default: ""
},
toolbar: {
type: Array,
required: false,
default() {
return [];
}
},
menubar: {
type: String,
default: "file edit insert view format table"
},
height: {
type: [Number, String],
required: false,
default: 360
},
width: {
type: [Number, String],
required: false,
default: "auto"
},
readOnly: {
type: Boolean,
default: false
}
},
data() {
return {
hasChange: false,
hasInit: false,
tinymceId: this.id,
fullscreen: false,
languageTypeList: {
en: "en",
zh: "zh_CN",
es: "es_MX",
ja: "ja"
}
};
},
computed: {
containerWidth() {
const width = this.width;
if (/^[\d]+(\.[\d]+)?$/.test(width)) {
// matches `100`, `'100'`
return `${width}px`;
}
return width;
}
},
watch: {
value(val) {
if (!this.hasChange && this.hasInit) {
this.$nextTick(() =>
window.tinymce.get(this.tinymceId).setContent(val || "")
);
}
},
readOnly: {
immediate: true,
handler(val) {
console.log(val);
this.setReadOnly(val);
}
}
},
mounted() {
this.init();
},
activated() {
console.log("tinymce activated");
if (window.tinymce) {
this.initTinymce();
}
},
deactivated() {
console.log("tinymce deactivated");
this.destroyTinymce();
},
destroyed() {
console.log("tinymce destroyed");
this.destroyTinymce();
},
methods: {
async init() {
// dynamic load tinymce from cdn
load(tinymceCDN, err => {
if (err) {
this.$message.error(err.message);
return;
}
console.log("下载");
this.initTinymce();
});
},
initTinymce() {
const _this = this;
window.tinymce.init({
selector: `#${this.tinymceId}`,
language: this.languageTypeList["zh"],
height: this.height,
body_class: "panel-body ",
object_resizing: false,
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
menubar: this.menubar,
plugins: plugins,
end_container_on_empty_block: true,
powerpaste_word_import: "clean",
code_dialog_height: 450,
code_dialog_width: 1000,
advlist_bullet_styles: "square",
advlist_number_styles: "default",
imagetools_cors_hosts: ["www.tinymce.com", "codepen.io"],
default_link_target: "_blank",
link_title: false,
// images_upload_url: "",
// images_upload_handler: function (blobInfo, succFun, failFun) {
// var file = blobInfo.blob();
// },
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
init_instance_callback: editor => {
if (_this.value) {
editor.setContent(_this.value);
}
_this.hasInit = true;
editor.on("NodeChange Change KeyUp SetContent", () => {
this.hasChange = true;
this.$emit("input", editor.getContent());
});
},
setup(editor) {
editor.on("FullscreenStateChanged", e => {
_this.fullscreen = e.state;
});
},
// it will try to keep these URLs intact
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
// https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
convert_urls: false,
// 整合七牛上传
images_dataimg_filter(img) {
setTimeout(() => {
const $image = $(img);
$image.removeAttr("width");
$image.removeAttr("height");
if ($image[0].height && $image[0].width) {
$image.attr("data-wscntype", "image");
$image.attr("data-wscnh", $image[0].height);
$image.attr("data-wscnw", $image[0].width);
$image.addClass("wscnph");
}
}, 0);
return img;
},
images_upload_handler(blobInfo, success, failure, progress) {
const formData = new FormData();
formData.append("file", blobInfo.blob());
console.log(formData);
vue.prototype.$http
.upload("/api/file/file/upload/uploadFile", formData)
.then(res => {
// vue.prototype.$http
// .get("/api/file/file/downloadById/" + res.content.id)
// .then(res => {
// console.log(res);
// });
success("/api/file/file/downloadById/" + res.content.id);
});
// progress(0);
// const token = _this.$store.getters.token;
// getToken(token).then(response => {
// const url = response.data.qiniu_url;
// const formData = new FormData();
// formData.append("token", response.data.qiniu_token);
// formData.append("key", response.data.qiniu_key);
// formData.append("file", blobInfo.blob(), url);
// // eslint-disable-next-line no-undef
// .upload(formData).then(() => {
// success(url);
// progress(100);
// });
// })
// .catch(err => {
// failure("出现未知问题,刷新页面,或者联系程序员");
// console.log(err);
// });
}
});
},
destroyTinymce() {
const tinymce = window.tinymce.get(this.tinymceId);
if (this.fullscreen) {
tinymce.execCommand("mceFullScreen");
}
if (tinymce) {
tinymce.destroy();
}
},
setContent(value) {
if (window.tinymce) {
window.tinymce.get(this.tinymceId).setContent(value);
}
},
getContent() {
window.tinymce.get(this.tinymceId).getContent();
},
setReadOnly(readOnly = true) {
const model = readOnly ? "readonly" : "design";
setTimeout(() => {
if (window.tinymce) {
window.tinymce.editors[this.tinymceId].setMode(model); // 开启只读模式
}
}, 800);
},
imageSuccessCBK(arr) {
arr.forEach(v =>
window.tinymce
.get(this.tinymceId)
.insertContent(`<img class="wscnph" src="${v.url}" >`)
);
}
}
};
</script>
<style lang="scss" scoped>
.tinymce-container {
position: relative;
line-height: normal;
}
.tinymce-container {
::v-deep {
.mce-fullscreen {
z-index: 10000;
}
}
}
#mceu_114 {
display: none;
}
.tinymce-textarea {
visibility: hidden;
z-index: -1;
}
.editor-custom-btn-container {
position: absolute;
right: 4px;
top: 4px;
/*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
z-index: 10000;
position: fixed;
}
.editor-upload-btn {
display: inline-block;
}
</style>
3
更多推荐
所有评论(0)