一、介绍

Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式。mavonEditor是国人开源的一款比较好用的markdown编辑器,GitHub地址:https://github.com/hinesboy/mavonEditor

二、安装

npm install mavon-editor --save

如果下载不了或安装失败可以(当然你得装了cnpm)

cnpm install mavon-editor --save

如果没装cnpm,也可以

npm install mavon-editor --save --registry=https://registry.npm.taobao.org

这是国人开发的,一般npm即可

三、使用

main.js:

    // 全局注册
    // import with ES6
    import Vue from 'vue'
    import mavonEditor from 'mavon-editor'
    import 'mavon-editor/dist/css/index.css'
    // use
    Vue.use(mavonEditor)
    new Vue({
        'el': '#main',
        data() {
            return { value: '' }
        }
    })

index.vue:

<template>
  <div class="app-container">
    <el-form :label-position="'left'" :model="markdownForm" :rules="rules"   label-width="60px" >
      <el-form-item label="标 题" prop="title">
        <el-input v-model="markdownForm.title"></el-input>
      </el-form-item>
    </el-form>
    <mavon-editor ref="md" @save="save" @imgAdd="imgAdd" @imgDel="imgDel" v-model="markdownForm.contentMarkdown" :codeStyle="markdown.codeStyle" :toolbars="markdown.toolbars"   />
    <br>
    <el-row>
      <el-col :span="2">
        <el-button @click="goback">返 回</el-button>
      </el-col>
      <el-col :span="2" :offset="20">
        <el-button type="primary" style="float: right;" @click="save">保 存</el-button>
      </el-col>

    </el-row>
  </div>
</template>

<script>
  import {getMarkdownArticle,saveMarkdownArticle} from '@/api/markdownArticle'
  import {uploadImg} from '@/api/markdownArticleImg'

  export default {
  data() {
    return {
      markdown:{
        codeStyle:'atom-one-dark',
        toolbars:{
          bold: true, // 粗体
          italic: true, // 斜体
          header: true, // 标题
          underline: true, // 下划线
          strikethrough: true, // 中划线
          mark: true, // 标记
          superscript: true, // 上角标
          subscript: true, // 下角标
          quote: true, // 引用
          ol: true, // 有序列表
          ul: true, // 无序列表
          link: true, // 链接
          imagelink: true, // 图片链接
          code: true, // code
          table: true, // 表格
          fullscreen: true, // 全屏编辑
          readmodel: true, // 沉浸式阅读
          htmlcode: true, // 展示html源码
          help: true, // 帮助
          /* 1.3.5 */
          undo: true, // 上一步
          redo: true, // 下一步
          trash: true, // 清空
          save: true, // 保存(触发events中的save事件)
          /* 1.4.2 */
          navigation: true, // 导航目录
          /* 2.1.8 */
          alignleft: true, // 左对齐
          aligncenter: true, // 居中
          alignright: true, // 右对齐
          /* 2.2.1 */
          subfield: true, // 单双栏模式
          preview: false, // 预览
        }
      },
      markdownForm : {
        articleId:null,
        title:"",
        contentMarkdown:'',
        contentHtml:null,
        type:0
      },
      rules: {
        title: [
          { required: true, message: '请输入标题', trigger: 'blur' },
          { min: 1, max: 80, message: '长度在1到80个字符', trigger: 'blur' }
        ]
      },
      lastSaveTime:null,
      timer:null
    }
  },
  created(){
    this.getArticle() 
  },
  mounted() {
    this.timer = setInterval(this.intervalSave, 2*60*1000);
  },
  beforeDestroy() {
    clearInterval(this.timer);
  },
  methods: {
   getArticle(){  //获取文章内容
     let id=this.$route.query.a
     if(id==null){
       this.markdownForm.contentMarkdown=''
     }else{
       getMarkdownArticle(id).then(r => {
         this.markdownForm.contentMarkdown=r.data.contentMarkdown==null?'':r.data.contentMarkdown
         this.markdownForm.articleId=r.data.articleId
         this.markdownForm.title=r.data.title
         this.markdownForm.type=r.data.type
       }).catch(e => {
         console.log(e)
       })
     }
   },
   save(){  //保存文章内容
     saveMarkdownArticle(this.markdownForm).then(r => {
       this.$message.success("保存成功")
       this.markdownForm.articleId=r.data.articleId
       this.lastSaveTime=new Date()
     }).catch(e => {
       console.log(e)
     })
   },
   intervalSave(){ //自动保存
      let now = new Date()
      if(now-this.lastSaveTime>=2*60*1000){
        saveMarkdownArticle(this.markdownForm).then(r => {
          this.$message.success("自动保存成功")
          this.lastSaveTime=new Date()
        }).catch(e => {
          console.log(e)
        })
      }
   },
   imgAdd(pos, file){ //添加图片,pos为位置
      let markdownImg = {},$vm=this.$refs.md
      markdownImg.base64Data=file.miniurl  //获取图片base64内容
      markdownImg.type=file.type
      uploadImg(markdownImg).then(r => {
        console.log(r)
        $vm.$img2Url(pos,process.env.VUE_APP_BASE_API+'/img/'+r.data) 
      }).catch(e => {
        console.log(e)
      })
    },
    imgDel(pos,url){ //删除图片,并不是修改就会触发,仅支持工具栏操作
      console.log(pos)
      console.log(url)
    }
  }
}
</script>

<style lang="scss">
.v-note-panel.shadow{
  min-height: 440px;  //设置编辑框最小高度
}
</style>

api/markdownArticle:

import request from '@/utils/request'

export function getMarkdownArticles() {
  return request({
    url: '/edu/markdown/articles',
    method: 'get'
  })
}
export function getMarkdownArticle(id) {
  return request({
    url: '/edu/markdown/article/'+id,
    method: 'get'
  })
}
export function saveMarkdownArticle(data) {
  return request({
    url: '/edu/markdown/article',
    method: 'post',
    data
  })
}

/**
 * 发布/取消发布
 * @param data
 */
export function updateStatus(data) {
  return request({
    url: '/edu/markdown/article/status',
    method: 'post',
    data
  })
}

/**
 * 删除
 * @param data
 */
export function del(data) {
  return request({
    url: '/edu/markdown/article',
    method: 'delete',
    data
  })
}

api/markdownArticleImg

import request from '@/utils/request'

export function uploadImg(data) {
  return request({
    url: '/edu/markdown/img',
    method: 'put',
    data
  })
}

utils/request仅是对axios的简单封装,没有特殊处理,参照vue-element-admin里request的写法

四、详细

props

name 名称type 类型default 默认值describe 描述
valueString 初始值
languageStringzh-CN语言选择,暂支持 zh-CN: 中文简体 , en: 英文 , fr: 法语, pt-BR: 葡萄牙语, ru: 俄语, de: 德语, ja: 日语
fontSizeString15px编辑区域文字大小
scrollStyleBooleantrue开启滚动条样式(暂时仅支持chrome)
boxShadowBooleantrue开启边框阴影
subfieldBooleantruetrue: 双栏(编辑预览同屏), false: 单栏(编辑预览分屏)
defaultOpenString edit: 默认展示编辑区域 , preview: 默认展示预览区域 , 其他 = edit
placeholderString开始编辑...输入框为空时默认提示文本
editableBooleantrue是否允许编辑
codeStyleStringcode-githubmarkdown样式: 默认github, 可选配色方案
toolbarsFlagBooleantrue工具栏是否显示
navigationBooleanfalse默认展示目录
shortCutBooleantrue是否启用快捷键
autofocusBooleantrue自动聚焦到文本框
ishljsBooleantrue代码高亮
imageFilterfunctionnull图片过滤函数,参数为一个File Object,要求返回一个Booleantrue表示文件合法,false表示文件不合法
imageClickfunctionnull图片点击事件,默认为预览,可覆盖
tabSizeNumber\ttab转化为几个空格,默认为\t
toolbarsObject如下例工具栏

 

events 事件绑定

name 方法名params 参数describe 描述
changeString: value , String: render编辑区发生变化的回调事件(render: value 经过markdown解析后的结果)
saveString: value , String: renderctrl + s 的回调事件(保存按键,同样触发该回调)
fullScreenBoolean: status , String: value切换全屏编辑的回调事件(boolean: 全屏开启状态)
readModelBoolean: status , String: value切换沉浸式阅读的回调事件(boolean: 阅读开启状态)
htmlCodeBoolean: status , String: value查看html源码的回调事件(boolean: 源码开启状态)
subfieldToggleBoolean: status , String: value切换单双栏编辑的回调事件(boolean: 双栏开启状态)
previewToggleBoolean: status , String: value切换预览编辑的回调事件(boolean: 预览开启状态)
helpToggleBoolean: status , String: value查看帮助的回调事件(boolean: 帮助开启状态)
navigationToggleBoolean: status , String: value切换导航目录的回调事件(boolean: 导航开启状态)
imgAddString: filename, File: imgfile图片文件添加回调事件(filename: 写在md中的文件名, File: File Object)
imgDelString: filename图片文件删除回调事件(filename: 写在md中的文件名)

代码高亮

如不需要hightlight代码高亮显示,你应该设置ishljs为false,默认开启所以不需要设置,主要是选择代码样式,即codeStyle属性,可以先到方案对应样式里找到你想要的样式,再到可选配色方案里找具体的对应名称

图片上传

<template>
    <mavon-editor ref=md @imgAdd="$imgAdd" @imgDel="$imgDel"></mavon-editor>
</template>
exports default {
    methods: {
        // 绑定@imgAdd event
        $imgAdd(pos, $file){
            // 第一步.将图片上传到服务器.
           var formdata = new FormData();
           formdata.append('image', $file);
           axios({
               url: 'server url',
               method: 'post',
               data: formdata,
               headers: { 'Content-Type': 'multipart/form-data' },
           }).then((url) => {
               // 第二步.将返回的url替换到文本原位置![...](0) -> ![...](url)
               /**
               * $vm 指为mavonEditor实例,可以通过如下两种方式获取
               * 1. 通过引入对象获取: `import {mavonEditor} from ...` 等方式引入后,`$vm`为`mavonEditor`
               * 2. 通过$refs获取: html声明ref : `<mavon-editor ref=md ></mavon-editor>,`$vm`为 `this.$refs.md`
               */
               $vm.$img2Url(pos, url);
           })
        }
    }
}

  • 默认大小样式为 min-height: 300px , min-width: 300px 可自行覆盖
  • 基础z-index: 1500
  • 仅用作展示可以设置props: toolbarsFlag: false , subfield: false, defaultOpen: "preview"

这里也提到了,当我们仅需要展示的时候,可以设置 toolbarsFlag: false , subfield: false, defaultOpen: "preview",即

<mavon-editor :toolbarsFlag="false"  :subfield="false" defaultOpen="preview" v-model="article.contentMarkdown" :codeStyle="markdown.codeStyle"/>

整理不易,感谢赞赏~~~~~

 

 

Logo

前往低代码交流专区

更多推荐