Vue3 项目中的 tinymce

617 阅读1分钟

最近项目中用到 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,
    };
  },
});