乐趣区

关于前端:在vue项目里使用tinymce富文本编辑器

最近在 vue 我的项目里应用到了 tinymce 富文本编辑器,途中遇到不少 bug,然而网上又没有很好的解决,最初摸索进去,记录一下。

下载 tinymce

这里并不需要用 npm 装置 tinymce,也不装置 tinymce-vue。网上有教程说 npm i tinymce 装置后,把 node_modules 里的文件拷贝进去到 public 文件里,而后在 index.html 里援用的。都不须要!间接上官网下载你须要的版本的 tinymce 包并解压,以及下载对应版本的中文语言包,将 zh_CN.js 文件放到 tinymce 的 langs 文件夹外面。

新建组件

在我的项目的 components 里,新建一个组件,例如取名 TinyEditor,并新建 index.vue 组件文件。将 tinymce 里的所有文件,拷贝到这个组件里。构造如下

组件文件

<template>
  <div id="tinyeditor"></div>
</template>

引入必须的文件 tinymce.min.js、theme.min.js,以及须要的插件、语言包。

import './tinymce.min.js';
import './plugins/lists/plugin.min.js';
import './plugins/code/plugin.min.js';
import './plugins/textpattern/plugin.min.js';
import './themes/silver/theme.min.js';
import './langs/zh_CN';

在款式局部引入款式文件

@import url('./skins/ui/oxide/skin.min.css');

增加插件

例如首行缩进、行高设置等官网没有提供的插件,下载下来后,间接放到 TinyEditor 下的 plugins 文件夹里,而后在组件文件里引入,留神引入程序要 tinymce.min.js 之后。

import './tinymce.min.js';
import './plugins/lists/plugin.min.js';
import './plugins/code/plugin.min.js';
import './plugins/textpattern/plugin.min.js';
import './plugins/indent2em/plugin.min.js';
import './plugins/lineheight/plugin.min.js';
import './themes/silver/theme.min.js';
import './langs/zh_CN';

残缺代码

这里并没有应用数据绑定,因而须要在初始化时将内容增加进去,并监听批改的事件。特地留神要在 destroyed 的时候清理对象,因为 tinymce 是一个全局对象。

<template>
  <div id="tinyeditor"></div>
</template>
<script>
// 去掉 html 标签,预防 xss 攻打
function removeTags(str, tagsToKeep) {const tagsRegExp = new RegExp(`<(?!\/?(${tagsToKeep.join('|')})\s*\/?>)[^>]+>`, 'gi');
  return str.replace(tagsRegExp, '');
}

import './tinymce.min.js';
import './plugins/lists/plugin.min.js';
import './plugins/code/plugin.min.js';
import './plugins/textpattern/plugin.min.js';
import './plugins/indent2em/plugin.min.js';
import './plugins/lineheight/plugin.min.js';
import './themes/silver/theme.min.js';
import './langs/zh_CN';

export default {
  name: 'editor',
  data() {
    return {
      editor: null,
      init: {
        selector: '#tinyeditor',
        height: 600,
        language: 'zh_CN', 
        plugins: 'lists code indent2em textpattern lineheight', // 插件
        toolbar: [
          'undo redo code | bold italic underline strikethrough | fontsizeselect | formatselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | indent2em lineheight',
          'indent outdent | bullist numlist | blockquote | removeformat',
        ], // 工具栏
        branding: false, // 去除版权信息
        menubar: false, // 去除菜单栏
        paste_preprocess: (pl, o) => {o.content = removeTags(o.content, 'sup,sub');
        },
        init_instance_callback: (editor) => {
          this.editor = editor;
          if (this.value) {editor.setContent(this.value); // 设置内容
          }
          // 监听内容变动的形式
          editor.on('NodeChange Change KeyUp SetContent', () => {this.$emit('input', editor.getContent());
          });
        }, // 初始化回调函数
      },
    };
  },
  props: {
    value: {
      type: String,
      default: '',
    },
  },
  mounted() {tinymce.init(this.init);
  },
  destroyed() {tinymce.remove(this.editor);
  },
};
</script>
<style scoped lang="scss">
@import url('./skins/ui/oxide/skin.min.css');
</style>

引入组件

我这里增加一个 v -if,因为我要在弹窗里应用,所以要确保每次敞开弹窗时要毁掉组件。

<tiny-editor v-if="open" v-model="content" @input="res => content = res"></tiny-editor>
退出移动版