Vue中使用editor.md预览文章

684 阅读1分钟

我正在参加「掘金·启航计划」

一、GitHub下载Editor.md

下载地址:pandao.github.io/editor.md/

二、public下新建static目录

将下载好的editor.md放入static目录中 image.png

开发预览组件

新建文件editormd-preview.vue 引入script: cnpm install --save scriptjs scriptjs:是一个异步JavaScript加载器和依赖关系管理器,具有惊人的轻量级功能。与许多其他脚本加载程序一样,$script.js允许您根据需要从任何URL加载脚本资源,而不阻止加载其他资源(如CSS和图像)。

<template>
  <div
    :id="id"
    class="markdown-view-container"
    @keydown.ctrl.83.prevent="save"
  >
    <!-- <link
      href="/static/editor.md/editor.md/css/editormd.preview.css"
      rel="stylesheet"
    > -->
    <!-- <link
      href="/static/editor.md/editor.md/css/editormd.platform.min.css"
      rel="stylesheet"
    > -->

    <textarea
      style="display:none;"
      v-html="content"
    />

    <!-- 放大图片 -->
    <!--        <BigImg v-if="showImg" @clickit="showImg = false" :imgSrc="imgSrc"></BigImg>-->
  </div>
</template>

<script>
import $s from 'scriptjs'

// import BigImg from '@/components/common/BigImg'
// import moduleName from '../../js'

export default {
  name: 'Editormd',
  props: {
    width: {
      type: String,
      default: '',
    },
    content: {
      type: String,
      default: '',
    },
    type: {
      type: String,
      default: 'editor',
    },
    id: {
      type: String,
      default: 'editor-md',
    },
    editorPath: {
      type: String,
      default: '/static/editor.md', // editormd文件夹所在路径
    },
    editorConfig: {
      type: Object,
      default () { // 对象或数组默认值必须从一个工厂函数获取
        return {
          path: '/js/editor.md/lib/',
          height: 300,
          taskList: true, // 任务完成图
          watch: false,
          placeholder: "本编辑器支持Markdown编辑,左边编写,右边预览",
          tex: true,  // 科学公式
          flowChart: true,  // 流程图
          sequenceDiagram: true,  // 时序图/序列图
          syncScrolling: "single", // 预览,编辑窗同步滚动
          toolbarIcons: [
            "undo", "redo", "|", "bold", "italic", "|", "image", "link", "||", "watch", "search",
          ],
          htmlDecode: "style,script,iframe,title,onmouseover,onmouseout,style",
          // imageUpload: true,
          imageFormats: [
            "jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP",
          ],
          // imageUploadURL: DocConfig.server+"/api/page/uploadImg",
          onload: () => {
            console.log('onload')
            console.log(this.instance);
          },
        };
      },
    },
  },
  // components:{
  //     BigImg
  // },
  data () {
    return {
      instance: null, // editormd的实例
      showImg: false,
      imgSrc: '',
    };
  },
  computed: {
  },
  mounted () {

    //加载依赖""
    $s([
      `../static/editor.md/examples/js/jquery.min.js`,
      `../static/editor.md/lib/raphael.min.js`,
      `../static/editor.md/lib/flowchart.min.js`,
    ], () => {
      $s([
        // `${this.editorPath}/../xss.min.js`,
        `../static/editor.md/lib/marked.min.js`,
        `../static/editor.md/lib/prettify.min.js`,
        `../static/editor.md/lib/underscore.min.js`,
        `../static/editor.md/lib/sequence-diagram.min.js`,
        `../static/editor.md/lib/jquery.flowchart.min.js`,
      ], () => {

        $s(`../static/editor.md/editormd.js`, () => {
          this.initEditor();
        });
        // $s(`${this.editorPath}/../highlight/highlight.min.js`, () => {
        //     hljs.initHighlightingOnLoad();
        // });
      });


    });
  },
  beforeDestroy () {
    //清理所有定时器
    for (let i = 1; i < 999; i++) {
      window.clearInterval(i);
    }
    //window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
  },
  methods: {
    initEditor () {
      this.$nextTick((editorMD = window.editormd) => {
        if (editorMD) {
          this.instance = editorMD.markdownToHTML(this.id, this.editorConfig);
          // this.deal_with_content();
        }
      });
    },
    //插入数据到编辑器中。插入到光标处
    insertValue (insertContent) {
      this.instance.insertValue(this.htmlDecode(insertContent));
    },
    getMarkdown () {
      return this.instance.getMarkdown();
    },
    editorUnwatch () {
      return this.instance.unwatch();
    },
    editorWatch () {
      return this.instance.watch();
    },
    clear () {
      return this.instance.clear();
    },
    //草稿
    // draft(){
    //     var that = this ;
    //     //定时保存文本内容到localStorage
    //     setInterval(()=>{
    //         localStorage.page_content= that.getMarkdown() ;
    //     }, 60000);
    //     //检测是否有定时保存的内容
    //     var page_content = localStorage.page_content ;
    //     if (page_content && page_content.length > 0) {
    //         localStorage.removeItem("page_content");
    //         that.$confirm('检测到有本地保存的草稿,是否恢复','提示',{
    //             confirmButtonText: '恢复',
    //             cancelButtonText: '放弃',
    //                 showClose:false
    //             }
    //         ).then(()=>{
    //             that.clear() ;
    //             that.insertValue(page_content) ;
    //             localStorage.removeItem("page_content");
    //         }).catch(()=>{
    //             localStorage.removeItem("page_content");
    //         });
    //     };
    // },

    //转义
    htmlDecode (str) {
      let s = "";
      if (str.length === 0) return "";
      s = str.replace(/&gt;/g, "&");
      s = s.replace(/&lt;/g, "<");
      s = s.replace(/&gt;/g, ">");
      s = s.replace(/&nbsp;/g, " ");
      s = s.replace(/&#39;/g, "'");
      s = s.replace(/&quot;/g, "\"");
      //s = s.replace(/<br>/g, "\n");
      return s;
    },
  },
};
</script>

<style lang="css">
/* @import "./../../../../../public/static/editor.md/css/editormd.css"; */
@import "./../../../../../public/static/editor.md/css/editormd.preview.css";
#editor-md {
  width: unset !important;
  padding: 0 !important;
}
#editor-md ul {
  list-style-type: disc !important;
}
#editor-md ul li {
  list-style-type: disc !important;
}
</style>

在查阅相关资料时,有的文档会要求使用Link引入标签引入样式文件,经尝试在Vue中不生效,所以引入样式文件时在style 中进行引入

import EditormdPreview from '../EditormdPreview/editormd-preview.vue';
<editormd-preview
        v-if="detailData.fileType === 'markdown'"
        :content="detailData.file ? detailData.file : question.summary"
 />