vue3 集成 tinymce 及自定义皮肤

内容分享2周前发布
0 0 0

【Vue 集成 TinyMCE 官方指南】

一、安装 tinymce-vue 包

npm install --save "@tinymce/tinymce-vue"

二、 使用 Tiny Cloud 或通过自托管 TinyMCE 来提供对 TinyMCE 的访问。

2.1 通过 Tiny Cloud 访问 TinyMCE(非最优解)

在 editor 元素中用 api-key 选项赋上你的 Tiny Cloud API key。

列如: 下面是我们自定义的一个公共组件src/components/TinymceEditor/index.vue

<template>
  <editor api-key= your-api-key  :init="{ /* your other settings */ }" />
</template>

<script lang="ts">
import Editor from  @tinymce/tinymce-vue 
export default {
   name:  TinymceEditor ,
   components: { Editor }
 }
</script>

2.2 TinyMCE 自托管

TinyMCE 可以通过以下方式自托管:

  • 2.2.1 独立于 Vue.js 应用部署 TinyMCE
    (我们重点讲这个,请移步第三部分。)

要在创建 Vue.js 应用时对 TinyMCE 进行独立部署,可以将 tinymce 脚本添加到 HTML 文件(/项目跟目录/public/index.html)的 <head><body> 的末尾,like:

<script src="/path/to/tinymce.min.js"></script>

更多有关自托管 TinyMCE 的信息,请参阅:【Installing TinyMCE】。

  • 2.2.2 使用模块打包器(如 Webpack、 Rollup.js、Browserify等)将 TinyMCE 与 Vue.js 应用打包在一起文档地址:【Usage with module loaders】。

三、独立部署 TinyMCE

3.1 下载自托管版本(离线版的) TinyMCE

https://www.tiny.cloud/get-tiny/self-hosted/

vue3 集成 tinymce 及自定义皮肤

把下载完后的js目录下的tinymce文件夹📁整个复制到项目的public目录下

vue3 集成 tinymce 及自定义皮肤

3.2 下载中文语言包

https://www.tiny.cloud/get-tiny/language-packages/

vue3 集成 tinymce 及自定义皮肤

下载完把zh_CN.js文件放在项目/public/tinymce/langs/下面

3.3 使用@tinymce/tinymce-vue组件

public下的文件在开发过程中可以直接用/访问到,我们这边用tinymceScriptSrc去指定加载我们本地的tinymce.min.js

<template>
    <editor
      :id="tinymceId"
      initialValue="<p>Initial editor content</p>"
      v-model="contentValue"
      :init="initOptions"
      tinymceScriptSrc="/tinymce/tinymce.min.js"
    />
</template>
<script lang="ts">
import { defineComponent, ref, computed } from  vue 
import Editor from  @tinymce/tinymce-vue 
import {
  filePickerCallback,
  uploadHandler,
} from  ./uploadHandler 
import { menubar, plugins, toolbar } from  ./config 

export default defineComponent({
  name:  Tinymce ,
  components: { TinymceEditor, EditorImage },
  props: {
    tinymceId: {
      type: String,
      default: function () {
        return (
           vue-tinymce-  +
          +new Date() +
          ((Math.random() * 1000).toFixed(0) +   )
        )
      },
    },
    modelValue: {
      type: String,
      default:   ,
    },
  },
  emits: [ update:modelValue ],
  setup(props, { emit }) {
    const hasChange = ref(false)
    const hasInit = ref(false)
    const fullscreen = ref(false)

    const initOptions = ref({
      language:  zh_CN ,
      skin:  animal ,
      content_css:  animal ,
      body_class:  panel-body ,
      height: props.height, // 注:引入autoresize插件时,此属性失效
      min_height: props.height,
      plugins: plugins,
      toolbar: toolbar,
      toolbar_sticky: true,
      toolbar_mode:  wrap , //  sliding 
      content_style:
         body { font-family:Helvetica,Arial,sans-serif; font-size:14px }, image: {max-width: 100%;} ,
      branding: false, // tiny技术支持信息是否显示
      link_title: false,
      default_link_target:  _blank ,
      convert_urls: false,
      end_container_on_empty_block: true,
      imagetools_cors_hosts: [ 106.54.168.208:1016 ],
      init_instance_callback: (editor: any) => {
        // tinymce 实例初始化时的回调
        if (props.moduleValue) {
          editor.setContent(props.modelValue)
        }
        hasInit.value = true
        editor.on( NodeChange Change KeyUp SetContent , () => {
          hasChange.value = true
          emit( update:modelValue , editor.getContent())
        })
      },
      image_title: true,
      // #参考 https://www.tiny.cloud/docs/configure/file-image-upload/#file_picker_callback
      file_picker_callback: filePickerCallback, // 选择文件后的处理
      images_upload_handler: uploadHandler, // 自定义文件上传函数
      setup: (editor: any) => {
        // tinymce 实例渲染之前的回调
        editor.on( FullscreenStateChanged , (e: any) => {
          fullscreen.value = e.state
        })
      },
    })

    return {
      initOptions,
      hasInit,
      fullscreen,
      contentValue: computed({
        get: () => props.modelValue,
        set: val => {
          emit( update:modelValue , val)
        },
      }),
    }
  },
})

vue3 集成 tinymce 及自定义皮肤

太具体的代码为了篇幅不贴了,可以看下去我的项目仓库看 ➡️ https://github.com/aizawasayo/animal-admin-vue3.git

3.4 自定义主题

第一,访问 http://skin.tiny.cloud/t5/

vue3 集成 tinymce 及自定义皮肤

下载下来的目录以你定义的皮肤名称为文件名,包含 skintool.json 配置文件和 skins 文件夹(新创建的皮肤)

vue3 集成 tinymce 及自定义皮肤

我们用这个新的 skins 文件夹替换原来的 /public/tinymce/skins 目录(如果不再需要tinymce的默认主题的话),将skintool.json放到/public/tinymce/下。

然后在初始化选项中将 skin 和 content_css 选项都定义为新皮肤名。

tinymce.init({
  // ...
  skin: "animal",
  content_css: "animal"
});

目前我的 tinymce 主题色就变成绿色系了。

vue3 集成 tinymce 及自定义皮肤

vue3 集成 tinymce 及自定义皮肤

将应用部署到 HTTP 服务器

官方文档还有关于部署到生产环境的配置。鉴于本篇是独立部署,直接放到了 public 目录下,不需要做更多处理。

vue3 集成 tinymce 及自定义皮肤

vite build打包完成后 public 下的文件都被原封不动地复制到 dist 目录下,那么把这些静态资源悉数传到 CDN 加速然后在生产环境使用 cdn 地址即可。具体步骤可见 ➡️ 【通过 jsDelivr + Github 对静态资源实现免费 CDN 加速】

📃.env.production

# .env.production

# cdn api
VITE_APP_CDN_API =  https://cdn.jsdelivr.net/gh/xxxxxxxx/cdn-for-tinymce@1.0/ 

📃src/components/Tinymce.vue

<template>
    <tinymce-editor
      :id="tinymceId"
      initialValue="<p>Initial editor content</p>"
      v-model="contentValue"
      :init="initOptions"
      :tinymceScriptSrc="tinymceSrc"
    />
</template>

export default defineComponent({
  setup(props, { emit }) {
    return {
      tinymceSrc: computed(() =>
        import.meta.env.VITE_APP_CDN_API
          ? import.meta.env.VITE_APP_CDN_API +  tinymce/tinymce.min.js 
          :  /tinymce/tinymce.min.js 
      ),
    }
  },
})

顺便提下,如果要把打包出来的dist/assets下的资源(图片、js、css)也放到另外的 cdn 引入,可以在vite.config.ts配置base(公共路径前缀)来实现:

// https://cn.vitejs.dev/config/
export default ({ mode }) => ({
  // base:  https://cdn.example.com/assets/ , // CDN(总是 HTTPS 协议)
  // base:  //cdn.example.com/assets/ , // CDN(协议一样)
  base: // 相当于 webpack 的 publicPath,如果 build.assetsDir 的资源需要放到 cdn,则需要改成 cdn 地址
    mode ===  production 
      ?  https://cdn.jsdelivr.net/gh/aizawasayo/xxxxxx@1.0/ 
      :  / ,
})

想了解更多,我们可以 Vite 为例,参阅:【静态资源处理】、【构建生产版本】。

TinyMCE 的 init 配置参数补充:

base_url<String>

指定 TinyMCE 主目录的基本 URL。
默认情况下,base_url 是包含 TinyMCE javascript 文件(如 tinymce.min.js)的目录,其他要引入的文件诸如主题和插件等内容会默认在这个目录下去查找。即都是在一处的,指定了tinymce.min.js地址的情况一般不用再配置。

如果另外指定了这个选项,那么需注意其它所有本应和 TinyMCE javascript 放在同一目录的文件,如皮肤、主题、插件等,都会基于这个配置路径去查找。

api-key<String>

Tiny Cloud API key。用 Tiny Cloud 进行部署时需要提供 给TinyMCE editor。

注册 Tiny Cloud API key,请访问 Tiny Account 注册页。要查找现有 Tiny 帐户的 Tiny Cloud API key,请登录并访问 Tiny Account Dashboard

默认值: no-api-key

tinymce-script-src:<String>

可使用 tinymce-script-src 属性来指定一个外部版本的 TinyMCE 以延迟加载。

skin_url <String>

默认情况下,会在引入的 tinymce.min.js 的根目录中(列如按照我们的部署就是/public/tinymce/下)查找 skins 文件夹。使用 skin_url 选项则可以自行指定皮肤目录的位置。
和 base_url场景类似,当从不同的基础位置(例如 cdn)加载 tinymce.min.jsskin(列如项目本地服务)时,这将超级有用。
当用到自定义主题时,一般我们还是会将皮肤相关规范地放在/public/tinymce/目录下,这种情况指定skin_url为: /tinymce/skins/ui/animal 即可,也比较方便维护管理。

举个tinymce.min.js用 cdn 地址的🌰:
此时我们的/public/tinymce/目录下只有这些文件了,其他诸如plugins、themes、icons都是和tinymce.min.js一样的 cdn 源引入:

vue3 集成 tinymce 及自定义皮肤

此时我们需要调整的就是本地皮肤和语言的路径,还有别忘了加上apiKey

<template>
    <editor
      :id="tinymceId"
      v-model="contentValue"
      :init="initOptions"
      apiKey="dkb23i61in9c5mdpxxxxxxxxxxxxxxxxxxdnt8k8hpogn2n"
      tinymceScriptSrc="https://cdn.jsdelivr.net/npm/tinymce@5.9.2/tinymce.min.js"
    />
</template>
export default defineComponent({
  name:  Tinymce ,
  setup(props, { emit }) {
    const initOptions = ref({
      language:  zh_CN ,
      language_url:  /tinymce/langs/zh_CN.js ,
      skin_url:  /tinymce/skins/ui/animal ,
      skin:  animal ,
      content_css:  /tinymce/skins/content/animal/content.min.css ,
  },
  return {
    initOptions
  }
})
</script>

总结:反正最后静态资源也是要用 cdn 加速,还不如一整个自托管而不是部分去用官方的 cdn,不易维护、配置麻烦不说,体验也一般。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...