VUE3集成Markdown编辑器(http://editor.md.ipandao.com/)

目录

背景信息

Editor.md是2015年开源的项目,那时还没有VUE3版本,所以网上也较少VUE3集成Editor.md的示例。不过还是有些大牛分享了集成的方法。

 集成方法

1、下载和安装editor.md、scriptjs及 jquery.js

2、封装一个组件EditorMarkdown,以下为 EditorMarkdown.vue的内容。

3、引用组件EditorMarkdown,以下为App.vue的内容。

运行效果

父组件往子组件传递参数(场景:单击文档的导航节点时可往编辑器中传值),完成编辑器的初始化。



背景信息

Editor.md是2015年开源的项目,那时还没有VUE3版本,所以网上也较少VUE3集成Editor.md的示例。不过还是有些大牛分享了集成的方法。

例如:

vue集成editor.md_流年ln的博客-CSDN博客_vue使用editor.mdk

可是不能直接使用,需要进行一些调整。经过不断尝试,调整成功。

 集成方法

1、下载和安装editor.md、scriptjs及 jquery.js

  • editor.md最新版本: v1.5.0,更新于 2015-06-09

 Github下载

 或者通过 NPM 安装:

npm install editor.md

将下载后的文件放置到VUE3项目的public/static目录下(VUE2是放置到与src并列的static目录中)。

放置好后的目录结构如下(EditorMarkdown.vue为下一步要创建的组件——集成了editor.md,且可获取Markdown内容和解析后的Html内容,可在任意页面中引用)。

  • 安装scriptjs
npm install scriptjs --save
  • 下载jquery.js

从官网下载:Download jQuery | jQuery

建议下载非压缩版的,便于调试,例如Download the uncompressed, development jQuery 3.6.1

将jquery.js放置到:static/editor.md/lib/jquery.js(下文组件中会引用此路径)。

2、封装一个组件EditorMarkdown,以下为 EditorMarkdown.vue的内容。

<template>
  <div>
    <link rel="stylesheet" href="/static/editor.md/css/editormd.css">
    <!-- editormd -->
    <button id="get-md-btn">Get Markdown</button>
    <button id="get-html-btn">Get HTML</button>
    <div id="editor" style="z-index: 10" />
  </div>
</template>

<script>
import scriptjs from 'scriptjs'

export default {
  name: 'EditorMarkdown',
  props: {
    modelValue: {
      type: String,
      required: false,
      default: ''
    },
    height: {
      type: String,
      required: false,
      default: '720px'
    }
  },
  data() {
    return {
      editor: {}
    }
  },
  mounted() {
    // 设置延迟初始化markdown编辑器, 因为只会初始化一次,需要等待数据加载完成之后再初始化
    setTimeout(() => {
      this.initEditor()
    }, 300)
  },
  methods: {
    initEditor() {
      (async() => {
        await this.fetchScript('/static/editor.md/lib/jquery.js')
        await this.fetchScript('/static/editor.md/editormd.js')
        // await this.fetchScript('/static/editor.md/editormd.amd.js')

        this.$nextTick(() => {
          // 内容
          var content = this.modelValue

          const editor = window.editormd('editor', {
            path: '/static/editor.md/lib/',
            height: this.height,
            emoji: true,
            // 开启图片上传,图片上传重写了的
            imageUpload: true,
            saveHTMLToTextarea: true,
            // 可分区域定制样式主题
            theme        : (localStorage.theme) ? localStorage.theme : "dark",
            editorTheme  : (localStorage.editorTheme) ? localStorage.editorTheme : "3024-night",
            previewTheme : (localStorage.previewTheme) ? localStorage.previewTheme : "default",

            imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp","ico"],
            // 这里需要考虑返回值,所以封装了一层
            imageUploadURL: '/markdown/upload', //需在服务端定义接口
            htmlDecode: true, // 识别html标签
            // 监听更新,更新父组件值
            change: function() {
              this.$emit('update:modelValue', this.getMarkdown())
            },
            // 退出全屏
            onfullscreen: function() {
              // 原生JS修改层级
              var editor = document.getElementById('editor')
              editor.style['z-index'] = 13
            },
            // 全屏
            onfullscreenExit: function() {
              // 原生JS修改层级
              var editor = document.getElementById('editor')
              editor.style['z-index'] = 10
            },
            // 加载完成后再设置内容
            onload: function() {
              this.setMarkdown(content)
              // 加载ctrl + v粘贴图片插件
              window.editormd.loadPlugin('/static/editor.md/plugins/image-handle-paste/image-handle-paste', function() {
                editor.imagePaste()
              })
            }
          })

          const vm = this
          // 监听,改变父组件的值
          editor.on('change', function() {
            vm.$emit('update:modelValue', this.getMarkdown())
          })

          // this.editor = editor

          // eslint-disable-next-line no-undef
          $("#get-md-btn").bind('click', function(){  //获取左侧Markdown内容
            alert(editor.getMarkdown());
          });


          // eslint-disable-next-line no-undef
          $("#get-html-btn").bind('click', function() { //获取右侧html内容
            alert(editor.getHTML());
          });

        })
      })()
    },
    fetchScript(url) {
      return new Promise((resolve) => {
        scriptjs(url, () => {
          resolve()
        })
      })
    }
  }
}
</script>

<style scoped>
/* 上传图片弹窗样式有点问题,可能是冲突了 */
#editor::v-deep(.editormd-dialog-header) {
  padding: 0 20px;
}
</style>



3、引用组件EditorMarkdown,以下为App.vue的内容。

<template>
<!--  <img alt="Vue logo" src="./assets/logo.png">-->
<!--  <HelloWorld msg="Welcome to Your Vue.js App"/>-->
  <h1>VUE3项目中引入 Editor.md</h1>

  <EditorMarkdown modelValue="Welcome to Your Vue.js 3 + TypeScript App"/>

</template>

<script>
// import HelloWorld from './components/HelloWorld.vue'
import EditorMarkdown from "@/components/EditorMarkdown.vue";


export default {
  name: 'App',
  components: {
    EditorMarkdown
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行效果

 单击上面的按钮可以分别获取左侧的Markdown内容(用于提交给服务端)和右侧的Html内容。

父组件往子组件传递参数(场景:单击文档的导航节点时可往编辑器中传值),完成编辑器的初始化。

修改APP.VUE的组件引用,通过组件EditorMarkdown 中定义的props/modelValue参数进行进行传值。

<EditorMarkdown modelValue="Welcome to Your Vue.js 3 + TypeScript App"/>

效果:编辑区显示了modelValue设置的值。