最近项目中用到 tinymce,现在来分享一下。 www.tiny.cloud/tinymce/
这里项目中的版本为
tinymce: 6.2.0
可以将其抽离为一个公用的组件:rich-text-editor
初始化配置
<template>
<textarea />
</template>
<script lang="tsx">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup(props) {
const init = () => {
(window as any).tinymce.init({
selector: `#${randomIdString}`,
language_url:
'https://talk-resource.oss-cn-hangzhou.aliyuncs.com/js/tinymce/langs/zh-Hans.js',
language: 'zh-Hans',
plugins:
'link lists image code table wordcount media table fullscreen preview pagebreak insertdatetime codesample emoticons charmap anchor',
toolbar: [
'undo redo | bold italic underline strikethrough | fontfamily fontsize Blocks',
'alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist blockquote table | forecolor backcolor removeformat',
'pagebreak hr | charmap emoticons insertdatetime | fullscreen preview | image media| link unlink anchor | codesample code',
],
font_family_formats:
'宋体; 仿宋;黑体;微软雅黑;楷体; 娃娃体-简;Arial=arial,helvetica,sans-serif; Courier New=courier new,courier,monospace; AkrutiKndPadmini=Akpdmi-n',
});
};
if (
!document.querySelector(
'script[src="https://talk-resource.oss-cn-hangzhou.aliyuncs.com/js/tinymce/tinymce.min.js"]'
)
) {
const scriptUrl = document.createElement('script');
scriptUrl.src =
'https://talk-resource.oss-cn-hangzhou.aliyuncs.com/js/tinymce/tinymce.min.js';
scriptUrl.onload = () => {
setTimeout(() => {
init();
}, 100);
};
document.body.appendChild(scriptUrl);
}
const getContent = (curPage: number) => {
return (window as any).tinymce.activeEditor.getContent();
};
const setContent = (value) => {
return (window as any).tinymce.activeEditor.setContent(value);
};
return {
getContent,
setContent,
};
},
});
</script>
传入 id,这里需要注意,传入 id 是为了使得每次进入页面,可以强制重新生成 tinymce 实例。
<template>
<textarea :id="randomId" />
</template>
<script lang="tsx">
import { defineComponent, ref } from 'vue';
export default defineComponent({
props: {
id: {
type: String,
default: 'mytextarea',
},
},
setup(props) {
const randomIdString = props.id + new Date().getTime();
const randomId = ref(randomIdString);
// ....
if (
!document.querySelector(
'script[src="https://talk-resource.oss-cn-hangzhou.aliyuncs.com/js/tinymce/tinymce.min.js"]'
)
) {
//....
} else if ((window as any).tinymce) {
// ...
}
//....
return {
// ...
randomId,
};
},
});
</script>
图片上传功能
<template>
<textarea :id="randomId" />
</template>
<script lang="tsx">
import { defineComponent, ref } from 'vue';
import axios from 'axios';
export default defineComponent({
props: {
id: {
type: String,
default: 'mytextarea',
},
},
setup(props) {
const init = () => {
(window as any).tinymce.init({
images_upload_handler: (blobInfo, success) =>
new Promise((resolve, reject) => {
const formData = new FormData();
formData.append('file', blobInfo.blob());
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
};
axios
.post(
'******',
formData,
config
)
.then((res) => {
const {
flag,
data: { url },
} = res;
if (flag) {
resolve(url);
}
});
}),
});
};
return {
randomId,
};
},
});
</script>
使用
import Editor from '@/components/rich-text-editor/index.vue';
<editor
id="experience-editor"
ref="editorRef"
style="height: 600px"
/>
提交的时候,获取其中的内容。或者,页面编辑的时候,向其中填充内容
export default defineComponent({
components: {
editor: Editor,
},
setup() {
const editorRef = ref(null);
const submit = async () => {
const article = editorRef.value.getContent();
};
onMounted(async () => {
setTimeout(() => {
editorRef.value.setContent('editContent');
}, 1000);
});
return {
editorRef,
submit,
};
},
});