有关于tui.editor升版

前言
其实在之前写过一篇关于tui.editor集成的文章,主要目的不是要告诉大家如何去集成,这些在官方的文档上都可以查阅。主要是记录一下在集成中遇到的问题和如何解决这些问题的过程。
本篇是由之前的v1.3.3升版至v2.1.0,改动还真的不小。不过升级之后呢有些之前的bug解决了,整个风格也有所变化。当然之前有关于自定义toolbar的疑惑也得到解决啦!之所以想要升版,是最近越来越多的同事在使用这个markdown编辑器,而且文档的编辑内容越来越长,在markdown模式下来回联滚的时候左右内容显示不一致,后来看了官方的文档和最近的更新历史有解决过这个问题,所以考虑升级。不过也发现了很多新内容,比如说有针对vue的vue-editor,还有react-editor、jquery-editor、editor(基础版),这些之前都是没有的。虽然我也是在vue的项目中使用,但是最后还是决定使用最基础的,这个后面会加以说明。
先安装

$ npm install --save @toast-ui/editor

再引入:

  import Editor from '@toast-ui/editor';
  import 'codemirror/lib/codemirror.css'; // Editor's Dependency Style
  import '@toast-ui/editor/dist/toastui-editor.css'; // Editor's Style
  import '@toast-ui/editor/dist/i18n/zh-cn';
  import uml from '@toast-ui/editor-plugin-uml';//uml plugin
  // import 'tui-color-picker/dist/tui-color-picker.css';//背景色plugin样式
  // import colorSyntax from '@toast-ui/editor-plugin-color-syntax';//背景色plugin
  //mermaid插件
  import mermaid from 'mermaid'
  //markmap插件
  import 'markmap/style/view.mindmap.css'
  require('markmap/lib/d3-flextree');
  const markmap = require('markmap/lib/view.mindmap');
  const parse = require('markmap/lib/parse.markdown');
  const transform = require('markmap/lib/transform.headings');

1.新建实例(预览模式)

initEditor() {
        let _this = this;
        //初次加载 显示md预览页 创建预览实例
        let sets = {
          height: _this.height,
          language:'zh-CN',
          viewer: true,//先创建的的是预览模式
          initialValue: '',
          toolbarItems: [
            'heading',
            'bold',
            'italic',
            'strike',
            'divider',
            'hr',
            'quote',
            'divider',
            'ul',
            'ol',
            'task',
            'indent',
            'outdent',
            'divider',
            'table',
            // 'image',
            'link',
            'divider',
            'code',
            'codeblock'
          ],
          plugins: [uml,this.mindmapPlugin,this.mermaidPlugin]
        };
        this.editor =  Editor.factory({
          el: this.$refs.viewer,
          ...sets
        })

        //mermaid配置
        let config = {
          theme: 'neutral',//'default', 'forest', 'dark', 'neutral'
          logLevel: 'fatal',
          securityLevel: 'strict',
          startOnLoad: true,
          arrowMarkerAbsolute: false,
          flowchart: {
            htmlLabels: false, //设为true宽度会变窄
            curve: 'linear',//cardinal
            useMaxWidth: true,
          },
          sequence: {
            diagramMarginX: 50,
            diagramMarginY: 10,
            actorMargin: 50,
            width: 150,
            height: 65,
            boxMargin: 10,
            boxTextMargin: 5,
            noteMargin: 10,
            messageMargin: 35,
            mirrorActors: true,
            bottomMarginAdj: 1,
            useMaxWidth: true,
            rightAngles: false,
            showSequenceNumbers: false,
          },
          gantt: {
            titleTopMargin: 25,
            barHeight: 40,
            barGap: 5,
            topPadding: 50,
            leftPadding: 75,
            gridLineStartPadding: 35,
            fontSize: 11,
            fontFamily: '"Open-Sans", "sans-serif"',
            numberSectionStyles: 4,
            axisFormat: '%Y-%m-%d',
          }
        };
        mermaid.flowchartConfig = {
          width: '100%',
        }
        mermaid.initialize(config);
      },

特别需要注意的是plugins参数,在老版本里面可不是叫plugins,叫exts,而且老版本里面存放的都是一些自己扩展的插件名称,但是新版本就不同了,可以存放方法。可以注意一下我的写法this.mindmapPlugin,this.mermaidPlugin这两个都 是有返回值的函数;上面代码使用 Editor.factory新建的是markdown预览模式,如果点击编辑,可使用new Editor新建markdown模式。也许有的需求可能不一样不需要预览,直接一上来就展示markdown,这些都可以随自己的需求新建需要的模式的;
2.插件注入
示例如下:

mermaidPlugin(){
        Editor.codeBlockManager.setReplacer('mermaid', function (content) {
          var mermaidId = 'mermaid-' + Math.random().toString(36).substr(2, 10);
          setTimeout(renderMermaid.bind(null, mermaidId, content), 0);
          return '
'; }); function renderMermaid(mermaidId, content) { var el = document.querySelector('#' + mermaidId); const cb = function (svgGraph) { el.innerHTML = svgGraph; }; const id = mermaidId + "-svg" mermaid.render(id, content, cb); } }, mindmapPlugin(){//mindmap插件注入 脑图部分 Editor.codeBlockManager.setReplacer('mindmap', function (content) { var mindmapId = 'mindmap-' + Math.random().toString(36).substr(2, 10); setTimeout(renderMindmap.bind(null, mindmapId, content), 0); let h = content.split(" ").length * 30; return `
`; }); function renderMindmap(mindmapId, content) { var el = document.querySelector('#' + mindmapId); const id = mindmapId + "-svg" setTimeout(() => { markmap('#' + id, transform(parse(content)), { preset: 'default', // or colorful linkShape: 'diagonal' // or bracket }); }, 0) el.innerHTML = ``; } },

这里使用到了Editor,其实吧使用vue-editor真的超级简便,但是扩展额外的插件时候愣是取不到Editor,被封装起来了。所以这也是我采用基础版的原因;还有插件注入这部分改动也不小,之前的版本API直接就不能用了,不过新版更好用;
3.自定义toolbar

initToolbars() {
        let _this = this;
        let toolbar = _this.editor.getUI().getToolbar();
        //上传图片
        _this.editor.eventManager.addEventType('insertImg');
        _this.editor.eventManager.listen('insertImg', function() {
          _this.insertImgClick();
        });
        toolbar.insertItem(toolbar.getItems().length - 1, {
          type: 'button',
          options: {
            name: 'toolbar-item',
            className: 'toast toast-img-icon',//自定义按钮的类名
            event: 'insertImg',//对应上文的eventManager添加的监听事件类型,通过点击触发
            tooltip: '上传图片',//鼠标hover自定义按钮的提示信息
          }
        });

        //网盘链接
        _this.editor.eventManager.addEventType('wpClick');
        _this.editor.eventManager.listen('wpClick', function () {
          _this.wpClick();
        });
        toolbar.insertItem(toolbar.getItems().length - 1, {
          type:'button',
          options: {
            event: 'wpClick',
            tooltip: '添加网盘文件',
            el:this.createLastButton('wp'),
            style: 'background:none;color:#333;'
          }
        });

        //mermaid扩展
        _this.editor.eventManager.addEventType('umlClick');
        _this.editor.eventManager.listen('umlClick', function () {
          _this.umlClick();
        });

        toolbar.insertItem(toolbar.getItems().length - 1, {
          type:'button',
          options: {
            event: 'umlClick',
            tooltip: '绘制UML图',
            el:this.createLastButton('uml'),
            style: 'background:none;color:#333;'
          }
        });

        //思维导图
        _this.editor.eventManager.addEventType('mindmapClick');
        _this.editor.eventManager.listen('mindmapClick', function () {
          _this.mindmapClick();
        });
        toolbar.insertItem(toolbar.getItems().length - 1, {
          type:'button',
          options: {
            event: 'mindmapClick',
            tooltip: '思维导图',
            el:this.createLastButton('mindmap'),
            style: 'background:none;color:#333;'
          }
        });

        //帮助
        _this.editor.eventManager.addEventType('helpClick');
        _this.editor.eventManager.listen('helpClick', function () {
          _this.helpClick();
        });
        toolbar.insertItem(toolbar.getItems().length - 1, {
          type:'button',
          options: {
            event: 'helpClick',
            tooltip: '帮助',
            el:this.createLastButton('help'),
            style: 'background:none;color:#333;'
          }
        });
      },

不知道有没有注意到createLastButton()这个方法,是用于注册每个自定义toolbar的样式的,这里我采用的是element-ui的icon十分简便;

createLastButton(tag) {//创建不同toolbar图标
        const button = document.createElement('button');
        if(tag == 'wp'){
          button.innerHTML = ``;
        }else if(tag == 'uml'){
          button.innerHTML = ``;
        }else if(tag == 'mindmap'){
          button.innerHTML = ``;
        }else if(tag == 'help'){
          button.innerHTML = ``;
        }
        return button;
      },

写到这里我之前的疑惑也解决了。因为在一开始的1.3.3版本中自定义toolbar是使用addButton这个API才加进去的,但是官方文档说已经弃用建议使用insertItem,但是那个时候呢可能是文档更新了插件没有更新吧,所以一直很纳闷,现在终于可以了。
最后呢,又有一个需求了,由于每个md内容过长,需要有目录。这就涉及到锚点问题,如何加进去呢?有待研究。。。

你可能感兴趣的:(有关于tui.editor升版)