vue整合editor.md解决多个editor.md同时共存问题v-model数据绑定vue-editor.md

vue整合editor.md解决多个editor.md同时共存问题v-model数据绑定

点击下载demo

定义editor.md为vue组件

安装 scriptjs

cnpm install --save scriptjs
在components文件夹下面创建一个组件
<template>
  <div class="markdown-editor-box">
    <link rel="stylesheet" href="/editormd/css/editormd.min.css">
    <div :id="editorId"></div>
  </div>
</template>
<script>
function uuid () {
    
    
  let s = []
  let hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    
    
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = s[13] = s[18] = s[23] = '-'
  return s.join('')
}

export default {
    
    
  model: {
    
    
    prop: 'content',
    event: 'onChangeContent'
  },
  props: {
    
    
    /**
     * 是否只做展示 真只展示 假则成为编辑器
     */
    show: {
    
    
      type: Boolean,
      default: false
    },
    /**
     * 标识 当内容改变时会传递标识过去  一般多个编辑器的时候可用用于标识
     */
    tag: {
    
    
      type: String,
      default: uuid()
    },
    /**
     * 标识 当内容改变时会传递标识过去  一般多个编辑器的时候可用用于标识
     */
    editorId: {
    
    
      type: String,
      default: uuid()
    },
    /**
     * 内容被改变事件 该事件接受一个参数
     * {
        markdown: editor.getMarkdown(),
        tag: this.tag,
        editorId: this.editorId,
        editor: editor,
        vm: this
      }
     */
    onchange: {
    
    
      type: Function
    },
    // 编辑器配置
    config: {
    
    
      type: Object
    },
    /**
     * 初始化加载的内容
     */
    content: {
    
    
      type: String,
      default: ''
    },
    /**
     * 延迟初始化数据时间,单位毫秒
     */
    delay: {
    
    
      type: Number,
      default: 0
    }
  },
  data: function () {
    
    
    return {
    
    
      editor: null,
      defaultConfig: {
    
    
        width: '100%',
        height: 680,
        path: '/editormd/lib/',
        // theme: 'dark',
        // previewTheme: 'dark',
        // editorTheme: 'pastel-on-dark',
        markdown: '',
        codeFold: true,
        // syncScrolling : false,
        saveHTMLToTextarea: true, // 保存 HTML 到 Textarea
        searchReplace: true,
        // watch : false,                // 关闭实时预览

        // toolbar  : false,             //关闭工具栏
        // previewCodeHighlight : false, // 关闭预览 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: true,
        imageFormats: ['jpg', 'jpeg', 'gif', 'png', 'bmp', 'webp'],
        imageUploadURL: './php/upload.php',
        // htmlDecode: 'style,script,iframe|on*', // 开启 HTML 标签解析,为了安全性,默认不开启
        htmlDecode: 'style,script,iframe', // 您可以过滤标签解码
        // toc             : false,
        // tocContainer    : "#custom-toc-container", // 自定义 ToC 容器层
        // gfm             : false,
        // tocDropdown     : true,
        // markdownSourceCode : true, // 是否保留 Markdown 源码,即是否删除保存源码的 Textarea 标签
        onload: function () {
    
    
          this.watch()
          // console.log('onload', this)
          // this.fullscreen();
          // this.watch().fullscreen();
          // this.setMarkdown("#PHP");
          // this.width("100%");
          // this.height(480);
          // this.resize("100%", 640);
        },
        onchange: function () {
    
    
          if (this.onContentChange && typeof this.onContentChange === 'function') {
    
    
            this.onContentChange(this)
          }
        }
      }
    }
  },
  methods: {
    
    

    getConfig () {
    
    
      return {
    
     ...this.defaultConfig, ...this.config }
    },
    getEditor () {
    
    
      return this.editor
    },
    watch () {
    
    
      return this.editor.watch()
    },
    unwatch () {
    
    
      return this.editor.unwatch()
    },
    previewing () {
    
    
      return this.editor.previewing()
    },
    getHTML () {
    
    
      return this.editor.getHTML()
    },
    getMarkdown () {
    
    
      return this.editor.getMarkdown()
    },
    setMarkdown (markdown) {
    
    
      return this.editor.setMarkdown(markdown)
    },
    onContentChange (editor) {
    
    
      let res = {
    
    
        markdown: editor.getMarkdown(),
        tag: this.tag,
        editorId: this.editorId,
        editor: editor,
        vm: this
      }
      if (this.onchange) {
    
    
        this.onchange(res)
      }
      this.$emit('onChangeContent', res.markdown)
    },

    initEditor (markdown) {
    
    
      let config = this.getConfig()
      if (markdown) {
    
    
        config.markdown = markdown
      }
      // 下载Emoji表情到本地 如果不需要则屏蔽即可
      // You can custom Emoji's graphics files url path
      window.editormd.emoji = {
    
    
        path: '/editormd/plugins/emoji-dialog/emoji/',
        ext: '.png'
      }

      // Twitter Emoji (Twemoji)  graphics files url path
      window.editormd.twemoji = {
    
    
        path: 'http://twemoji.maxcdn.com/72x72/',
        ext: '.png'
      }
      // 下载Emoji表情到本地 如果不需要则屏蔽即可

      config.onload = function () {
    
    
        setTimeout(() => {
    
    
          if (this._vm && this._vm.content) {
    
    
            this.setMarkdown(this._vm.content)
          }
        }, this.delay)
        this.watch()
      }
      this.$nextTick(() => {
    
    
        this.editor = window.editormd(this.editorId, config)
        this.editor.onContentChange = this.onContentChange
        this.editor._vm = this
      })
    }
  },
  mounted () {
    
    
    this.initEditor(this.content)
  }
}
</script>

在vuex store全局中加载所需js等文件

目录截图

在这里插入图片描述

安装 scriptjs

actions.js文件

// content 为 当前模块对象 data为调用该函数时传递的对象 外面使用dispatch("函数名称", data)方法调用这里的函数
import scriptjs from 'scriptjs'

export function testAction1 (content, data) {
    
    
}

// 这里可以吧content解构出来 如果需要那个就拆出来
export function testAction2 ({
    
     commit, dispatch, getters, rootGetters, rootState, state }, data) {
    
    
}

const fetchScript = function (url) {
    
    
  return new Promise((resolve) => {
    
    
    scriptjs(url, () => {
    
    
      resolve()
    })
  })
}

export function loadJs ({
    
     commit, dispatch, getters, rootGetters, rootState, state }, data) {
    
    
  return new Promise((resolve, reject) => {
    
    
    if (!state.loading.loadJs && window.editormd) {
    
    
      resolve()
      return
    }
    if (state.loading.loadJs) {
    
    
      let num = 0
      let index = setInterval(() => {
    
    
        try {
    
    
          if (!state.loading.loadJs && window.editormd) {
    
    
            try {
    
    
              resolve()
            } catch (e) {
    
    
            }
            clearInterval(index)
          }
        } catch (e) {
    
    
        }

        num++
        if (num > 100) {
    
    
          try {
    
    
            reject('超时退出')
          } catch (e) {
    
    
          }
          clearInterval(index)
        }
      }, 200)
      return
    }
    commit('setLoadinLoadJS', true);
    (async () => {
    
    
      await fetchScript('/jquery.min.js')
      await fetchScript('/editormd/lib/marked.min.js')
      await fetchScript('/editormd/lib/prettify.min.js')
      await fetchScript('/editormd/lib/raphael.min.js')
      await fetchScript('/editormd/lib/underscore.min.js')
      await fetchScript('/editormd/lib/sequence-diagram.min.js')
      await fetchScript('/editormd/lib/flowchart.min.js')
      await fetchScript('/editormd/lib/jquery.flowchart.min.js')
      await fetchScript('/editormd/editormd.min.js')
      resolve()
      commit('setLoadinLoadJS', false)
    })()
  })
}

vuex的mutations文件

export function setLoadinLoadJS (state, status) {
    
    
  state.loading.loadJs = status
}

vuex的state文件

export default function () {
    
    
  return {
    
    
    loading: {
    
    
      loadJs: false
    },
    editors: {
    
    }
  }
}

最后使用例子

<template>
  <div class="row" v-if="isShow">
    <div class="col-12">
      <markdown editor-id="article_dec" :onchange="onchangeEditor" tag="article_dec"
                v-model="article.desc"></markdown>
    </div>
    <div class="col-12">
      <markdown editor-id="article_content" :onchange="onchangeEditor" tag="article_content"
                v-model="article.content"></markdown>
    </div>
  </div>
</template>

<script>
import Markdown from './components/editormd.vue'

export default {
    
    
  name: 'x',
  components: {
    
     Markdown },
  data () {
    
    
    return {
    
    
      isShow: false,
      article: {
    
    
        desc: '',
        content: ''
      }
    }
  },
  created () {
    
    
    // -----------------------------------注意-------------------------------------------------.
    // 请到editor.md官网下载所有文件 然后放到静态资源文件里  最后在store文件中定义路径
    // -----------------------------------注意-------------------------------------------------.

    // 加载所需js 如果多次调用的话 放心只加载一次 多次调用等待加载完毕 如果已加载则自动回调
    this.$store.dispatch('editor/loadJs').then(e => {
    
    
      // 加载完毕显示 editor.md
      this.isShow = true
    })
  },
  methods: {
    
    
    onchangeEditor (e) {
    
    
      console.log(e)
    }
  }
}
</script>

<style scoped>

</style>

猜你喜欢

转载自blog.csdn.net/it2299888/article/details/111882310