vue2中TinyMCE的使用记录

在项目中引入tinymce

npm install tinymce@5.10.3 -S
npm install @tinymce/tinymce-vue@3.0.1 -S

依赖包移动

以上两条命令通过npm拉取了tinymce的依赖包,可以在node_modules 中找到 tinymce文件夹,将tinymce目录拷贝到 static目录下,其中skins是必需的,其他按需引入,根据名称可知道用途。
需要汉化的可以在官网下载语言包,汉化包地址,下载完成后将解压后的文件夹存放在与刚才那些文件相同的位置
引入包的安装位置

引入编辑器

接下来就可以在你的vue组件中引入编辑器了,推荐将编辑器封装成component,在view页面中调用即可,例如我的view页面:
doc/index.vue

<template>
  <div class="doc-box">
    <div class="editor-box">
      <TEditor></TEditor>
    </div>
    <!-- <button @click="test">测试</button> -->
  </div>
</template>
<script>
  import TEditor from '@/components/MyTiny'
  export default {
    name: 'TinyDoc',
    components: {
      TEditor,
    },
    data() {
      return { show: true }
    },
    created() {},
    mounted() {},
    methods: {},
  }
</script>

<style scoped>
  .doc-box {
    padding: 10px;
    height: 100%;
  }
</style>

引用的是封装好的编辑器组件
MyTiny/index.vue

<template>
  <div class="tinymce-editor">
    <Editor
      v-model="myValue"
      :init="init"
      :api-key="apiKey"
      :disabled="disabled"
    />
    <button @click="onClick()">测试</button>
  </div>
</template>

<script>
  // import { fileUpload } from '@/api/cms'
  import tinymce from 'tinymce/tinymce'
  import Editor from '@tinymce/tinymce-vue'

  // import 'tinymce/themes/modern/theme'
  import 'tinymce/themes/silver/theme'
  import 'tinymce/icons/default/icons'
  import 'tinymce/plugins/image' // 插入上传图片插件
  import 'tinymce/plugins/media' // 插入视频插件
  import 'tinymce/plugins/table' // 插入表格插件
  import 'tinymce/plugins/link' // 超链接插件
  import 'tinymce/plugins/code' // 代码块插件
  import 'tinymce/plugins/lists' // 列表插件
  import 'tinymce/plugins/contextmenu' // 右键菜单插件
  import 'tinymce/plugins/wordcount' // 字数统计插件
  import 'tinymce/plugins/colorpicker' // 选择颜色插件
  import 'tinymce/plugins/textcolor' // 文本颜色插件
  import 'tinymce/plugins/fullscreen' // 全屏
  // import 'tinymce/plugins/help' // 帮助
  import 'tinymce/plugins/charmap'

  import 'tinymce/plugins/print' // 打印
  import 'tinymce/plugins/preview' // 预览
  import 'tinymce/plugins/hr' // 水平线

  import 'tinymce/plugins/spellchecker'
  import 'tinymce/plugins/imagetools'
  import 'tinymce/plugins/noneditable'
  // import 'tinymce/plugins/save'
  // import 'tinymce/plugins/tabfocus'
  // import 'tinymce/plugins/textpattern'
  // import 'tinymce/plugins/template'

  import 'tinymce/icons/default/icons'
  import 'tinymce/plugins/advlist' //高级列表
  import 'tinymce/plugins/anchor' //锚点
  import 'tinymce/plugins/autolink' //自动链接
  import 'tinymce/plugins/autoresize' //编辑器高度自适应,注:plugins里引入此插件时,Init里设置的height将失效
  import 'tinymce/plugins/autosave' //自动存稿
  import 'tinymce/plugins/charmap' //特殊字符
  import 'tinymce/plugins/code' //编辑源码
  import 'tinymce/plugins/codesample' //代码示例
  import 'tinymce/plugins/directionality' //文字方向
  import 'tinymce/plugins/emoticons' //表情
  import 'tinymce/plugins/fullpage' //文档属性
  // import "tinymce/plugins/fullscreen"; //全屏
  import 'tinymce/plugins/help' //帮助
  // import 'tinymce/plugins/hr' //水平分割线
  import 'tinymce/plugins/importcss' //引入css
  import 'tinymce/plugins/insertdatetime' //插入日期时间
  // import 'tinymce/plugins/link' //超链接
  // import 'tinymce/plugins/lists' //列表插件
  // import 'tinymce/plugins/media' //插入编辑媒体
  // import 'tinymce/plugins/image' // 插入图片
  import 'tinymce/plugins/nonbreaking' //插入不间断空格
  import 'tinymce/plugins/pagebreak' //插入分页符
  import 'tinymce/plugins/paste' //粘贴插件
  // import 'tinymce/plugins/preview' //预览
  // import 'tinymce/plugins/print' //打印
  import 'tinymce/plugins/quickbars' //快速工具栏
  import 'tinymce/plugins/save' //保存
  import 'tinymce/plugins/searchreplace' //查找替换
  // import 'tinymce/plugins/spellchecker'  //拼写检查,未加入汉化,不建议使用
  import 'tinymce/plugins/tabfocus' //切入切出,按tab键切出编辑器,切入页面其他输入框中
  // import 'tinymce/plugins/table' //表格
  import 'tinymce/plugins/template' //内容模板
  // import 'tinymce/plugins/textcolor' //文字颜色
  import 'tinymce/plugins/textpattern' //快速排版
  import 'tinymce/plugins/toc' //目录生成器
  import 'tinymce/plugins/visualblocks' //显示元素范围
  import 'tinymce/plugins/visualchars' //显示不可见字符
  // import 'tinymce/plugins/wordcount' //字数统计

  export default {
    components: {
      Editor,
    },
    props: {
      // 传入一个value,使组件支持v-model绑定
      value: {
        type: String,
        default: '',
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      plugins: {
        type: [String, Array],
        default:
          'lists image media table textcolor wordcount contextmenu preview',
      },
      toolbar: {
        type: [String, Array],
        default:
          "undo redo |  formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image media table | removeformat table| fontsizeselect | fontselect'",
      },
    },
    data() {
      return {
        apiKey: 'jzlds2e6urz6akm9wxp4f70mnwg83d8fovsialqazxowyity',
        // 配置文件服务器的静态访问路径前缀
        // static_web_preurl: 'http://localhost/files/hxzy_img/',
        // 初始化配置
        init: {
          placeholder: '在这里输入文字',
          language_url: '/tinymce/langs/zh-Hans.js', // 汉化路径
          language: 'zh_CN',
          skin_url: '/tinymce/skins/ui/oxide',
          height: 1200, // 编辑器高度,可以考虑获取窗口高度,以适配不同设备屏幕
          end_container_on_empty_block: true,
          powerpaste_word_import: 'clean',
          advlist_bullet_styles: 'square',
          advlist_number_styles: 'default',
          imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
          default_link_target: '_blank',
          link_title: false,
          media_live_embeds: true,
          content_style: 'img {max-width:100%;} html{background-color: #fff;}', // 直接自定义可编辑区域的css样式
          images_upload_url: '/api/attch/upload',
          nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
          // plugins: this.plugins,
          // toolbar: this.toolbar,
          // @ts-nocheckplugins: 'link lists image code table colorpicker textcolor wordcount contextmenu',
          plugins:
            'advlist anchor autolink autosave code codesample colorpicker  contextmenu directionality toc  fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount',
          // toolbar:'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat | table',
          toolbar: [
            'searchreplace bold italic underline strikethrough fontselect fontsizeselect  alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample',
            'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen',
          ],
          fontsize_formats: '8pt 10pt 12pt 14pt 18pt 24pt 36pt', // 第二步
          font_formats:
            "微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings",
          branding: false,
          elementpath: false, //隐藏底栏的元素路径
          // inline: true, //开启内联模式
          // icons: 'custom',
          menubar: true,

          file_picker_types: 'media',
        },
        myValue: this.value,
      }
    },
    watch: {
      value(newValue) {
        this.myValue = newValue
      },
      myValue(newValue) {
        this.$emit('input', newValue)
      },
    },
    mounted() {
      tinymce.init({})
    },
    methods: {
      onClick(e) {
        this.$emit('onClick', e, tinymce)
        console.log(tinymce.editors[0].selection.getBookmark())
        tinymce.editors[0].getContent()
      },
      // 可以添加一些自己的自定义事件,如清空内容
      clear() {
        this.myValue = ''
      },
    },
  }
</script>
<style scoped>
  .tinymce-editor {
    padding: 0 100px;
  }
</style>

另一种写法:

<template>
  <div>
    <div id="tinymce"></div>
    <input type="button" value="获得内容" @click="getContent" />
  </div>
</template>
<script>
  import tinymce from 'tinymce/tinymce' //tinymce默认hidden,不引入不显示
  import 'tinymce/themes/silver/theme' //编辑器主题
  import 'tinymce/plugins/link' //超链接
  import 'tinymce/plugins/paste' //粘贴过滤
  import 'tinymce/plugins/preview' //预览
  import 'tinymce/plugins/media'
  import 'tinymce/plugins/image'
  import 'tinymce/plugins/advlist'
  import 'tinymce/plugins/code' // 源代码

  export default {
    data() {
      return {}
    },

    mounted() {
      console.log('执行')
      this.initTiny()
    },

    methods: {
      // 初始化编辑器
      initTiny() {
        var tinyID = 'tinymce'
        tinymce.init({
          selector: '#' + tinyID,
          height: 1280,
          language_url: '/tinymce/langs/zh-Hans.js', // 汉化路径
          language: 'zh-Hans',
          statusbar: false,
          skin_url: '/tinymce/skins/ui/oxide', // 编辑器皮肤
          content_css: `/tinymce/skins/content/default/content.css`, // 编辑器样式
          plugins: 'link media image advlist code', // 插件
          toolbar:
            'undo redo | styleselect | bold italic aligncenter| link image media code', // 菜单栏
          auto_focus: true,
          plugins:
            'fullpage contentmenu bbcode auto print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autosave bdmap indent2em autoresize formatpainter axupimgs',

          toolbar:
            'code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \
          styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
          table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | bdmap indent2em lineheight formatpainter axupimgs',

          min_height: 400,
          /*content_css: [ //可设置编辑区内容展示的css,谨慎使用
        '/static/reset.css',
        '/static/ax.css',
        '/static/css.css',
    ],*/
          fontsize_formats: '12px 14px 16px 18px 24px 36px 48px 56px 72px',
          font_formats:
            '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;',
          // link_list: [
          //   { title: '预置链接1', value: 'http://www.tinymce.com' },
          //   { title: '预置链接2', value: 'http://tinymce.ax-z.cn' },
          // ],
          // image_list: [
          //   {
          //     title: '预置图片1',
          //     value: 'https://www.tiny.cloud/images/glyph-tinymce@2x.png',
          //   },
          //   {
          //     title: '预置图片2',
          //     value: 'https://www.baidu.com/img/bd_logo1.png',
          //   },
          // ],
          // image_class_list: [
          //   { title: 'None', value: '' },
          //   { title: 'Some class', value: 'class-name' },
          // ],
          importcss_append: true,
          //自定义文件选择器的回调内容
          file_picker_callback: function (callback, value, meta) {
            if (meta.filetype === 'file') {
              callback('https://www.baidu.com/img/bd_logo1.png', {
                text: 'My text',
              })
            }
            if (meta.filetype === 'image') {
              callback('https://www.baidu.com/img/bd_logo1.png', {
                alt: 'My alt text',
              })
            }
            if (meta.filetype === 'media') {
              callback('movie.mp4', {
                source2: 'alt.ogg',
                poster: 'https://www.baidu.com/img/bd_logo1.png',
              })
            }
          },
          toolbar_sticky: true,
          autosave_ask_before_unload: false,
        })
        //解决第二次加载编辑器无法显示编辑器内容的问题
        if (tinymce.editors.length > 0) {
          tinymce.execCommand('mceFocus', true, tinyID)
          tinymce.execCommand('mceRemoveEditor', true, tinyID)
          tinymce.execCommand('mceAddEditor', true, tinyID)
        }
      },
      // 点击获取内容
      getContent() {
        var cnt = tinymce.editors['tinymce'].getContent()
        console.log(cnt)
        alert(cnt)
      },
    },
  }
</script>
<style scoped></style>

其中汉化路径要注意,对应的是public文件夹下你移动进去的语言包langs
官网现在的包里的js文件名为zh-Hans.js,名称要一致,并且编辑器组件中的language: ‘zh_CN’,这一字段变量名,要与zh-Hans.js中变量名的一致(目前官网都叫zh-Hans),否则无法识别则汉化不成功。
以上第二种方法封装的组件可能会有只能加载一次编辑器,第二次加载不成功的问题,所以代码中的

//解决第二次加载编辑器无法显示编辑器内容的问题
        if (tinymce.editors.length > 0) {
          tinymce.execCommand('mceFocus', true, tinyID)
          tinymce.execCommand('mceRemoveEditor', true, tinyID)
          tinymce.execCommand('mceAddEditor', true, tinyID)
        }

这段即为了解决这个问题。

结束

好了,这样在你的vue项目中就可以使用tinyMCE富文本编辑器了,这款编辑器的API极其丰富,可以提供各种各样的操作,以满足项目中的各种特殊需求。
如果你只是想简单地在页面中使用富文本编辑器输入内容,建议使用wangEditor,其优势劣势在我其他的博客中有介绍。

GitHub 加速计划 / vu / vue
207.55 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:3 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 5 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐