tinymce 是一款基础组件十分丰富,不断维护更新的富文本编辑器。在它的 Github项目 简介中如此描述自己:

The world's #1 JavaScript library for rich text editing. Available for React, Vue and Angular

简而言之: 我是宇宙第一的编辑器,我支持当前最流行的三个框架。

我会分成3篇文章介绍:

  • 编辑器的基本使用和一些简单插件的配置
  • 一些复杂插件的配置,和集成Vue
  • 编写自定义插件
  • Why Tinymce

  • 基础组件丰富,简单配置即可使用;
  • 本身有收费版和免费版,可盈利性保证了其持续维护和创新,开发版其实也完全够用;
  • 提供的开发拓展API也比较简单,适合持续集成;
  • 开发文档虽然是英文版,但言简意赅,示例丰富,并且跟随版本实时更新,对比市面上其他编辑器好太多了
  • 本文使用的版本是 5.0.13

    Tinymce的核心文件和插件、皮肤、主题样式等文件都是分离的,使用时,只需在HTML中引入核心文件(tinymce.js)即可。

    <script src="https://fe.120yibao.com/common/tinymce/5.0.13/tinymce.min.js"></script>
    

    在生成新的编辑器实例时,需要传入配置文件,tinymce会根据配置自动引入对应的插件、皮肤、主题文件,默认使用相对路径(相对于tinymce.js)的方式。

    const editor = Tinymce.init({
        //会自动引入link插件
        // https://fe.120yibao.com/common/tinymce/5.0.13/plugins/link/plugin.min.js
        plugins: ['link'],  
        //会自动引入silver主题
        // https://fe.120yibao.com/common/tinymce/5.0.13/themes/silver/theme.min.js
        theme: 'silver',
        //会自动引入oxide皮肤
        // https://fe.120yibao.com/common/tinymce/5.0.13/skins/ui/oxide/skin.min.css
        skin: "oxide"
    

    而这些相对路径的关系,跟npm包的对应关系是一样的。

    npm i tinymce
    

    我们看下npm包的目录结构

    ├── jquery.tinymce.js ├── jquery.tinymce.min.js ├── plugins │   ├── advlist │   │   ├── index.js │   │   ├── plugin.js │   │   └── plugin.min.js │   ├── anchor │   │   ├── index.js │   │   ├── plugin.js │   │   └── plugin.min.js │   ├── autolink │   │   ├── index.js │   │   ├── plugin.js │   │   └── plugin.min.js ├── skins │   ├── content │   │   ├── default │   │   │   ├── content.css │   │   │   └── content.min.css │   │   ├── document │   │   │   ├── content.css │   │   │   └── content.min.css │   │   └── writer │   │   ├── content.css │   │   └── content.min.css │   └── ui │   ├── oxide │   │   ├── content.css │   │   ├── content.inline.css │   │   ├── content.inline.min.css │   │   ├── content.min.css │   │   ├── content.mobile.css │   │   ├── content.mobile.min.css │   │   ├── fonts │   │   │   └── tinymce-mobile.woff │   │   ├── skin.css │   │   ├── skin.min.css │   │   ├── skin.mobile.css │   │   └── skin.mobile.min.css │   └── oxide-dark │   ├── content.css │   ├── content.inline.css │   ├── content.inline.min.css │   ├── content.min.css │   ├── content.mobile.css │   ├── content.mobile.min.css │   ├── fonts │   │   └── tinymce-mobile.woff │   ├── skin.css │   ├── skin.min.css │   ├── skin.mobile.css │   └── skin.mobile.min.css ├── themes │   ├── mobile │   │   ├── index.js │   │   ├── theme.js │   │   └── theme.min.js │   └── silver │   ├── index.js │   ├── theme.js │   └── theme.min.js ├── tinymce.js └── tinymce.min.js

    所以,如果要使用CDN的方式使用tinymce的话,直接按照这个目录格式上传即可。

    也可以使用npm进行引入,但是每个插件、主题、皮肤都要单独引入,比较麻烦,不建议使用。

    // Import TinyMCE
    import tinymce from 'tinymce/tinymce';
    // A theme is also required
    import 'tinymce/themes/silver';
    // Any plugins you want to use has to be imported
    import 'tinymce/plugins/paste';
    import 'tinymce/plugins/link';
    // Initialize the app
    tinymce.init({
      selector: '#tiny',
      plugins: ['paste', 'link']
    
    <template>
    	<div class="default-tinymce">
    		<textarea id="editor"></textarea>
    	</div>
    </template>
    <script>
    import Tinymce from 'tinymce'
    export default {
      name: 'DefaultTinymce',
      mounted () {
        Tinymce.init({
          selector: '#editor'
    </script>
    

    此示例只配置了唯一的必填配置selector,即textarta元素的标识,此参数值支持类似于CSS选择器的参数格式。

    此示例除了使用了入口文件(tinymce.js),也会引入默认的主题和皮肤文件。

    初始化成功后,textarea的值会与一个iframe绑定,在富文本编辑区域的操作,其实都是在iframe中的操作,而内容则会自动同步到textarea里。

    tinymce 有三种模式可选:经典模式(classic,默认)、行内模式(inline)、清爽模式(Distraction-free)。

    经典模式是最常见的,也就是工具栏搭配输入区域,通过工具栏的按钮插入、修改、格式化内容,我们也选用这种模式作为业务的主要模式。

    后两种模式也各有特点,但是与我们实际的应用场景不太匹配,故再次不多做介绍。有兴趣可以自行了解。

    多个编辑器

    如果一个页面中需要多个编辑器,有两种方法:

    一个是结合className选择器,使用一次 tinymceinit 方法,生成多个实例,多个实例会共用一套配置;

    示例代码:

    <template>
    	<div class="default-tinymce">
            <h2>编辑器1</h2>
    		<textarea class="editor"></textarea>
            <h2>编辑器2</h2>
    		<textarea class="editor"></textarea>
    	</div>
    </template>
    <script>
    import Tinymce from 'tinymce'
    export default {
      mounted () {
        Tinymce.init({
          selector: '.editor'
    </script>
    

    另一种是,需要几个编辑器,便使用tinymceinit 方法生成几种实例,生成的实例彼此无关

    示例代码:

    <template>
    	<div class="default-tinymce">
            <h2>编辑器1</h2>
    		<textarea class="editor1"></textarea>
            <h2>编辑器2</h2>
    		<textarea class="editor2"></textarea>
    	</div>
    </template>
    <script>
    import Tinymce from 'tinymce'
    export default {
      mounted () {
        Tinymce.init({
          selector: '.editor1'
        Tinymce.init({
          selector: '.editor2'
    </script>
    

    编辑器配置

    可以将编辑器的语言配置为中文

    tinymce.init({
        selector: '#myTextarea',
        language: 'zh_CN'
    
  • 可以设置language_url,覆盖默认地址。
  • tinymce.init({
        selector: '#myTextarea',
        language_url: 'https://fe.120yibao.com/common/tinymce/5.0.13/langs/zh_CN_01.js'
    
  • 也可以在项目中配置语言文件:
  • import Language from './language'
    Tinymce.addI18n('zh_CN_01', Language)
    tinymce.init({
        selector: '#myTextarea',
        language: 'zh_CN_01'
    

    附:官方多语言文件下载地址

    以下配置大致涵盖了tinymce的基础配置,具体我会分章节在下面说明

    tinymce.init({
        selector: '#myTextarea',
        // 编辑器的皮肤,有 oxide oxide-dark
        skin: 'dark',
        // 编辑器宽高
        width: 600,
        height: 300,
        // 用到的插件
        plugins: [
          'advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker',
          'searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking',
          'save table contextmenu directionality emoticons template paste textcolor'
        // 编辑区域内容样式
        content_css: 'css/content.css',
        // 工具栏的配置项
        toolbar: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | print preview media fullpage | forecolor backcolor emoticons'
    

    除了默认的配置,如果想拓展编辑器的功能,tinymce提供的方式就是插件。

    官方的插件很丰富,文档也很详细,大多数情况下,我只需要官方提供的插件即可。

    激活插件也很简单,只需要做了相应配置即可。

    比如,我们想要拓展一个查看编辑器内容HTML源码的功能,只需要如下配置:

    tinymce.init({
      selector: '#editor',
      plugins: 'code'
    

    menubar的位置,多了一个Tool的分组,分组里有一个source code的项,点击即可查看源码

    如果我们不习惯使用menubar,而是习惯使用toolbar,我们只需要如下配置:

    tinymce.init({
      selector: '#editor',
      toolbar: 'code',
      plugins: 'code'
    

    toolbar位置上多了一个查看源码的图标,点击是相同的功能

    有时候,这些基础的功能可能满足不了我们的需求,我们可能对这些插件进行配置。

    tinymce.init({
      selector: '#editor',
       toolbar: "numlist bullist",
      plugins: 'lists'
    

    示例中,我们配置了list组件,它支持无序(ul)列表和有序列表的功能,但是列表样式是固定的,我们可以引入新的插件advlist,并配置

    tinymce.init({
      selector: '#editor',
      toolbar: 'bullist numlist',
      plugins: 'lists advlist'
    

    此时,我们发现我们可以选择样式了,有多种样式供我们选择,如果我们想固定某种样式,我们可以这样配置:

    tinymce.init({
      selector: '#editor',
      toolbar: 'bullist numlist',
      plugins: 'lists advlist',
      advlist_number_styles: 'lower-alpha'
    

    我们发现可选项只有一个了

    每个插件有哪些配置项、配置参数和配置值,官方文档中都有详细的描述

    自定义编辑器UI

    themeskin 我们直接使用默认的即可,无需折腾。

    从上面的示例中,我们也知道基本上所有东西我们都可以去自定义的,比如隐藏不使用的menubar、调整按钮在toolbar中的位置等。

    tinymce.init({
      selector: '#editor',
      // 隐藏menubar
      menubar: false,
      // 隐藏 statusbar
      statusbar: false,
      // 隐藏品牌标识
      branding: false,
      // 设置最大宽高
      max_height: 500,
      max_width: 500,
      // 设置最小宽高
      min_height: 100,
      min_width: 400
    

    这些配置不太重要,一般一次配置之后就不会有改动。

    这里会写一下编辑器用到的插件的介绍、配置、和使用,太简单的插件和没用到的插件不在此说明。

    Advanced Code Editor

    此插件为付费插件

    此插件可美化代码预览时候的视图,并且还有收起/展开标签的功能。配置此插件后,需要移除code插件。

    tinymce.init({
      selector: "textarea",  // change this value according to your HTML
      plugins: "advcode",
      toolbar: "code"
    

    AutoLink

    此插件可在输入形如「www.qq.com」的链接时,自动将文本转化为超链接,空格和换行键都可以触发

    tinymce.init({
      selector: "textarea",  // change this value according to your HTML
      plugins: "autolink"
    

    nonbreaking

    键盘的Tab键,默认是切换到下一个元素的focus。此可以改变这个默认行为。

    需要注意的是,table插件中也有改变改默认行为的代码,所以要在table插件之后引用该插件。

    tinymce.init({
      selector: "textarea",  // change this value according to your HTML
      plugins: "nonbreaking",
      // 此配置会改变默认行为,会在光标之后添加三个空格。
      nonbreaking_force_tab: true
    

    autosave

    此插件会自动保存编辑器的内容到localStorage。会同时存储两个字段,一个是内容,一个是存储时间。

    可以配置自动保存的时间间隔,一般以秒为单位;也可以配置内容存储的过期时间,一般以分钟为单位,超过这个时间段,数据会从localStorage中被清除。

    tinymce.init({
      selector: "textarea",  // change this value according to your HTML
      plugins: "autosave",
      // 自动保存的时间间隔
      autosave_interval: '30s',
      // 自动保存的数据存储的最大时间
      autosave_retention: '30m'
    

    powerpaste

    此插件为付费插件

    此插件可以保留剪切板内容的样式、文档结构。

    tinymce.init({
      selector: "textarea",  // change this value according to your HTML
      plugins: "powerpaste",
       * 粘贴前是否保留文本样式
       * @param 'clean' 不保留
       * @parma 'merge' 保留
       * @parma 'prompt' 询问用户
      powerpaste_word_import: 'prompt',
      powerpaste_html_import: 'prompt',
       * 在粘贴到富文本之前,可以修改粘贴的内容。内容已经DOM格式化
       * @param plugin
       * @param args
       * @returns {Promise<void>}
      paste_postprocess (plugin, args) {}
    

    下一篇:Tinymce - 宇宙第一富文本编辑器?[2]

  • tinymce官方文档
  • 分类:
    前端
    标签: