tinymce离线vue3-ts组件实现过程

2022-01-14  本文已影响0人  LL天HH土

本来想用tinymce的vue版本直接用的,可是应用过后出现一系列的问题:

所以,决定配置一套离线版的tinymce!

步骤

  vue3+ts+elementUI
  1. 第一步:下载离线版的tinymce
    https://www.tiny.cloud/get-tiny/self-hosted/
    注意:可以下载Dev版本,也可以下载Prodtinymce.js默认加载原始文件,不加载压缩过后.min的文件;
    如果要下载Dev的话,需要添加配置如下代码:
    Snipaste_2022-01-14_17-42-59.png
  1. 第二步:整理目录
    把下面红圈里的文件复制出来,放到项目的/public目录下

    目录
  2. 第三步:下载中文包
    https://www.tiny.cloud/get-tiny/language-packages/
    并把下载好的zh_CN.js文件放在项目/public/tinymce/langs/下面

  3. 使用@tinymce/tinymce-vue组件

<template>
  <Editor v-model="val" :init="config" :id="eid" />
</template>

<script lang="ts">
import { computed, watch, onMounted } from "vue";
import "/@public/tinymce/tinymce.min";
import Editor from "@tinymce/tinymce-vue";
import "/@public/tinymce/tinymce.d";

declare global {
  interface Window {
    tinymce: any;
  }
}

import configDefault from "./default-config";
import getUploadHandler from "./getUploadHandler";

export default {
  components: {
    Editor,
  },
  props: {
    value: {
      type: String,
      default: "",
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    uploadUrl: {
      type: String,
      default: "",
    },
    init: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  emits: ["update:value"],
  setup(props: any, context: any) {
    const eid = Date.now();

    // 双向绑定
    const val = computed({
      get() {
        return props.value;
      },
      set(newVal: string) {
        context.emit("update:value", newVal);
      },
    });

    // 配置对象
    const config = computed(() => {
      const obj = Object.assign(configDefault, props.init);
      obj.images_upload_handler = getUploadHandler(props.uploadUrl);

      return obj;
    });

    // 监听disabled
    watch(
      () => props.disabled,
      (val: boolean) => {
        if (window.tinymce.editors && window.tinymce.editors[eid])
          window.tinymce.editors[eid].setMode(val ? "readonly" : "design");
      }
    );

    onMounted(() => {
      window.tinymce.editors[eid].setMode(val ? "readonly" : "design");
    });

    return {
      val,
      config,
      eid,
    };
  },
};
</script>
// default-config.ts
export default {
 base_url: '/tinymce',
 suffix: ".min",
 language: "zh_CN",
 height: 400,
 menubar: false,

 plugins: "quickbars lists paste table link image",
 toolbar:
   "link image table | cut copy paste | fontsizeselect | forecolor backcolor | bold italic underline | numlist bullist indent outdent alignjustify alignleft aligncenter alignright",
 fontsize_formats:
   "8px 10px 12px 14pt 16px 18px 20px 22px 24px 26px 28px 30px 36px",
}
// getUploadHandler.ts
const getUploadHandler = (uploadUrl: string): any => {
  return (
    blobInfo: any,
    success: any,
    failure: any,
    progress: any
  ) => {

    let xhr: any, formData: any;
    xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open("POST", uploadUrl);

    xhr.upload.onprogress = function (e: any) {
      progress((e.loaded / e.total) * 100);
    };

    xhr.onload = function () {
      var json;
      if (xhr.status == 403) {
        failure("HTTP Error: " + xhr.status, { remove: true });
        return;
      }
      if (xhr.status < 200 || xhr.status >= 300) {
        failure("HTTP Error: " + xhr.status);
        return;
      }
      json = JSON.parse(xhr.responseText);
      const url = json.data.url;
      if (!json || typeof url != "string") {
        failure("Invalid JSON: " + xhr.responseText);
        return;
      }
      success(url);
    };

    xhr.onerror = function () {
      failure(
        "Image upload failed due to a XHR Transport error. Code: " +
        xhr.status
      );
    };

    formData = new FormData();
    formData.append("file", blobInfo.blob(), blobInfo.filename());

    xhr.send(formData);
  }
}

export default getUploadHandler
  1. 优化

  2. 参考资料

上一篇 下一篇

猜你喜欢

热点阅读