1、下载editor.md

http://pandao.github.io/editor.md/

2、解压后,放入工程目录的static目录中

3、安装scriptjs

    cnpm install --save scriptjs

4、编写组件

<template>
  <div class="markdown-editor-box">
    <link rel="stylesheet" href="/static/editor.md/css/editormd.min.css">
    <div :id="editorId"></div>
  </div>
</template>
<script>
  import scriptjs from 'scriptjs'
  import { defaultConfig } from '../../config/editor.md'
  export default {
    props: {
      editorId: {
        'type': String,
        'default': 'markdown-editor'
      },
      onchange: { // 内容改变时回调,返回(html, markdown, text)
        type: Function
      },
      config: { // 编辑器配置
        type: Object
      },
      initData: {
        'type': String
      },
      initDataDelay: {
        'type': Number, // 延迟初始化数据时间,单位毫秒
        'default': 0
      }
    },
    data: function () {
      return {
        editor: null,
        timer: null,
        doc: {},
        jsLoadOver: false
      }
    },
    methods: {
      fetchScript: function (url) {
        return new Promise((resolve) => {
          scriptjs(url, () => {
            resolve()
          })
        })
      },
      getConfig: function () {
        return { ...defaultConfig, ...this.config }
      },
      getEditor: function () {
        return this.editor
      },
      getDoc: function () {
        return this.doc
      },
      watch: function () {
        return this.editor.watch()
      },
      unwatch: function () {
        return this.editor.unwatch()
      },
      previewing: function () {
        return this.editor.previewing()
      },
      getHTML: function () {
        return this.editor.getHTML()
      },
      getMarkdown: function () {
        return this.editor.getMarkdown()
      },
      setMarkdown: function (markdown) {
        return this.editor.setMarkdown(markdown)
      },
      init (id) {
        let vm = this
        let editor = vm.$store.state.editor
        if (editor.goEdit) {
          editor.goEdit = false
        } else {
          editor.isEditing = false
        }
        vm.axios.get('/interfaceApi/getDocById/' + id)
          .then(function (response) {
            let doc = response.data.pageInfo.list[0]
            vm.doc = doc
            let md = doc.content
            vm.initEditor(md)
          })
          .catch(function (error) {
            vm.$message({
              message: error.data.serverResult.resultMessage,
              type: 'error'
            })
          })
      },
      initEditor: function (markdown) {
        let vm = this
        let config = vm.getConfig()
        if (markdown) {
          config.markdown = markdown
        }
        (async () => {
          await vm.fetchScript('/static/editor.md/jquery.min.js')
          await vm.fetchScript('/static/editor.md/editormd.min.js')
          vm.jsLoadOver = true
          vm.$nextTick(() => {
            vm.editor = window.editormd(vm.editorId, config)
            vm.editor.on('load', () => {
              setTimeout(() => { // hack bug: 一个页面多个编辑器只能初始化其中一个数据问题
                vm.initData && vm.editor.setMarkdown(vm.initData)
              }, vm.initDataDelay)
            })
            vm.onchange && vm.editor.on('change', () => {
              let html = vm.editor.getPreviewedHTML()
              vm.onchange({
                markdown: vm.editor.getMarkdown(),
                html: html,
                text: window.$(html).text()
              })
            })
          })
        })()
      }
    },
    mounted: function () {
      let vm = this
      let docId = vm.$router.currentRoute.name
      vm.init(docId)
      vm.timer = setInterval(function () {
        if (vm.editor && vm.jsLoadOver) {
          try {
            vm.watch()
            vm.previewing()
            vm.previewing()
            window.clearInterval(vm.timer)
            vm.timer = null
          } catch (e) {
          }
        }
      }, 80)
    },
    destroyed: function () {
      let vm = this
      if (vm.timer != null) {
        window.clearInterval(vm.timer)
        vm.timer = null
      }
    }
  }
</script>

5、编写配置文件

const defaultConfig = {
  width: "100%",
  height: 600,
  path: '/static/editor.md/lib/',
  // theme: 'dark',
  // previewTheme: 'dark',
  // editorTheme: 'pastel-on-dark',
  markdown: '',      // 默认填充内容
  lineWrapping: true, // 编辑框不换行
  codeFold: true,                 // 代码折叠
  placeholder: '请输入...',
  syncScrolling: true,
  saveHTMLToTextarea: true,       // 保存 HTML 到 Textarea
  searchReplace: true,
  watch: true,                                // 实时预览
  htmlDecode: "style,script,iframe|on*",      // 开启 HTML 标签解析,为了安全性,默认不开启
  toolbar: true,                  //工具栏
  previewCodeHighlight: true,     // 预览 HTML 的代码块高亮,默认开启
  emoji: true,
  taskList: true,
  tocm: true,                     // Using [TOCM]
  tex: true,                      // 开启科学公式TeX语言支持,默认关闭
  flowChart: true,                // 开启流程图支持,默认关闭
  sequenceDiagram: true,          // 开启时序/序列图支持,默认关闭,
  // dialogLockScreen: false,      // 设置弹出层对话框不锁屏,全局通用,默认为true
  // dialogShowMask: false,        // 设置弹出层对话框显示透明遮罩层,全局通用,默认为true
  // dialogDraggable: false,       // 设置弹出层对话框不可拖动,全局通用,默认为true
  // dialogMaskOpacity: 0.4,       // 设置透明遮罩层的透明度,全局通用,默认值为0.1
  // dialogMaskBgColor: "#000",    // 设置透明遮罩层的背景颜色,全局通用,默认为#fff
  // imageUpload: false,
  // imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
  // imageUploadURL: "./php/upload.php",
  // onload: function() {
  //    // this.fullscreen();
  //    // this.unwatch();
  //    // this.watch().fullscreen();
  //    // this.setMarkdown("#PHP");
  //    // this.width("100%");
  //    // this.height(480);
  //    // this.resize("100%", 640);
  // },
};
export {
  defaultConfig,
};

6、 在页面中使用

      <tw-markdown-view v-if="!editor.isEditing" ref="markdownView"></tw-markdown-view>

 

7、在具体页面中调用组件中的方法

      watchHtml: function () {
        this.$refs['markdown'].watch()
      },
      unWatchHtml: function () {
        this.$refs['markdown'].unwatch()
      },

8、编辑工具栏配置,在第五步的配置文件的 defaultConfig 内部,找个地方加上下面这段,return后面的数组就是需要使用的工具栏按钮,上面注掉的是从githup上面,千辛万苦从一个问题解答中找到的全部的工具栏按钮列表。

  toolbarIcons : function() {
    //["undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info"]
    return ["bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|",
      "h1", "h2", "h3", "h4", "h5", "h6", "|",
      "hr", "code", "preformatted-text", "code-block", "table", "pagebreak", "|",
      "goto-line", "preview", "clear"]
  },

总结:

a、感觉这个工具很不错,编辑栏提供的工具挺多的,还算不错吧。

b、最开始没有写预览组件,预览时通过调用编辑界面的全窗口预览html方法,然后隐藏掉那个closed按钮来解决的。后面已经加上了预览组件,请看本系列第二篇文章。

c、我实际运用的时候没有使用这个工具的文件上传功能,一是因为网上文档都语焉不详,二是感觉editor.md对文件接口返回的属性名称貌似还有点限制?不符合我们已经存在的文件接口定义,所以最后是自己在页面上加了个文件上传按钮实现的。上传后用过js代码处理在编辑器中进行展示。

    //  上传成功
    uploadSuccess: function (rep) {
      if (rep.fileInfos != null && rep.fileInfos.length > 0) {
        let vm = this
        let filePath = rep.fileInfos[0].localPath
        if (filePath) {
          let fileUrl = vm.$store.state.fileServiceUrl + filePath
          let mdUrl = null
          let markdown = vm.$refs['markdown']
          if (vm.isImage(filePath)) {
            mdUrl = '![](' + fileUrl + ')'
          } else {
            mdUrl = fileUrl
          }
          let newMd = markdown.getMarkdown() + '\n' + mdUrl
          markdown.setMarkdown(newMd)
          markdown.watch()
        }
      }
    },

 

 

代码参考来源:http://www.lwl.tech/post/3 ,我这里对原作者的代码做了些修改删减,非常感谢该作者提供的示例。

 

Logo

前往低代码交流专区

更多推荐