博客地址:http://www.globm.top/blog/1/detail/27
效果图
mavon-editor markdown 编辑器
项目使用mavon-editor markdown编辑器,由于项目需要存储在数据库中的是md文件,所以需要通过marked转译为HTML文件
引入mavon-editor
//安装
npm i mavon-editor
//引入
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
Vue.use(mavonEditor)
//使用
<template>
<mavon-editor
v-model="content"
:placeholder="'Edit ···'"
ref="md"
@imgAdd="$imgAdd"
@imgDel="$imgDel"
@change="change"
:toolbars="toolbars"
:toolbarsBackground="'#f9f9f9'"
style="height: calc(100vh - 50px)"
/>
</template>
//参数
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: false, // 全屏编辑
readmodel: false, // 沉浸式阅读
htmlcode: true, // 展示html源码
help: true, // 帮助
/* 1.3.5 */
undo: true, // 上一步
redo: true, // 下一步
trash: true, // 清空
save: false, // 保存(触发events中的save事件)
/* 1.4.2 */
navigation: true, // 导航目录
/* 2.1.8 */
alignleft: true, // 左对齐
aligncenter: true, // 居中
alignright: true, // 右对齐
/* 2.2.1 */
subfield: true, // 单双栏模式
preview: false // 预览
}
//methods
methods: {
$imgAdd (pos, $file) {
// 第一步.将图片上传到服务器.
var formdata = new FormData()
formdata.append('image', $file)
this.img_file[pos] = $file
this.$http({
url: '/api/edit/uploadimg',
method: 'post',
data: formdata,
headers: { 'Content-Type': 'multipart/form-data' }
}).then((res) => {
let _res = res.data
// 第二步.将返回的url替换到文本原位置![...](0) -> ![...](url)
this.$refs.md.$img2Url(pos, _res.url)
})
},
$imgDel (pos) {
delete this.img_file[pos]
},
change (value, render) {
this.html = render
},
// 提交
submit () {
console.log(this.content)
console.log(this.html)
}
}
注:该编辑器支持代码块高亮,可通过codeStyle自定义配置,本项目为了灵活运用,使用的是自定义的代码样式
具体参数请参考mavon-editor官方文档
导入文件
数据库存储数据为md文件,所以需要转译为html文件
安装
npm install marked
转译
import marked from 'marked' //引入
//通过marked()转译
this.article.html = marked(this.article.content)
代码块高亮显示
引入
npm install highlight.js
配置
新建hljs.js,注册全局指令
import Vue from 'vue'
import hljs from 'highlight.js'
import 'highlight.js/styles/googlecode.css' // 样式文件
Vue.directive('highlight', function (el) {
let blocks = el.querySelectorAll('pre code')
blocks.forEach((block) => {
hljs.highlightBlock(block)
})
})
main.js引入hljs.js
import './plugins/hljs'
组件中使用
<div class="markdown-body" v-html="article.content" v-highlight></div>
mavon-editor 编辑器需要单独导入css文件
import 'mavon-editor/dist/markdown/github-markdown.min.css'
问题(按需使用):这样使用会在页面渲染的时候会出现高亮效果,但是这导致的问题是,切换路由的时候代码高亮会消失。之所以产生这种现象,这跟 hljs.initHighlightingOnLoad()的定义有关,因为只执行一次。
可以重写 hljs.initHighlighting()方法,在组件的中是使用 hljs.highlightCode(),每次页面加载的时候都会执行渲染代码的逻辑
//在main.js中
import 'highlight.js/styles/googlecode.css'
import hljs from 'highlight.js'
hljs.highlightCode = function () {
//自定义highlightCode方法,将只执行一次的逻辑去掉
let blocks = document.querySelectorAll('pre code');
[].forEach.call(blocks, hljs.highlightBlock);
};
//在组件中
export default {
mounted(){
hljs.highlightCode()
}
}
代码块添加行号
新建mavon.js
import $ from 'jquery'
import Vue from 'vue'
export const addCodeBtn = _ => {
//markdown代码存放在pre code 标签对中
$('pre code').each(function () {
let lines = $(this).text().split('\n').length - 1
//添加有序列表
let $numbering = $('
').addClass('pre-numbering')
//添加复制按钮,此处使用的是element-ui icon 图标
let $copy = $('').addClass('el-icon-document-copy code-copy')
$(this)
.parent()
.addClass('code')
.append($numbering)
.append($copy)
for (let i = 0; i <= lines; i++) {
$numbering.append($(''))
}
})
//监听复制按钮点击事件
$('pre.code i.code-copy').click(e => {
let text = $(e.target).siblings('code').text()
let element = $(' + text + '')
$('body').append(element)
element[0].select()
document.execCommand('Copy')
element.remove()
//这里是自定义的消息通知组件
Vue.prototype.$notice.success({
msg: '代码复制成功'
})
})
}
在css文件中设置样式
pre.code {
position: relative;
border-radius: 3px;
border: 1px solid #C3CCD0;
overflow: hidden;
padding-left: 60px!important;
code {
line-height: 30px!important;
}
ol.pre-numbering {
position: absolute;
top: 0;
left: 5px;
line-height: 30px;
padding: 16px 0;
list-style-type:none;
counter-reset:sectioncounter;
margin-bottom: 0;
li{
margin-top: 0!important;
&:before{
content:counter(sectioncounter) "";
counter-increment:sectioncounter;
display: inline-block;
width: 40px;
text-align: center;
border-right: solid 1px rgba(0, 0, 0, 0.53);
}
}
}
i.code-copy{
position: absolute;
top:0;
right: 0;
background-color: #464d5e;
padding: 3px;
margin: 3px 3px 0 0;
font-size: 11px;
border-radius: inherit;
color: #f1f1f1;
cursor: pointer;
display: none;
}
&:hover i.code-copy{
display: block;
}
}
last
在组件中引入
import { addCodeBtn } from '../assets/js/mavon'
this.$nextTick(_ => {
addCodeBtn()
})