Vue CLI3 使用 marked 渲染 Markdown 格式数据

说明

首先需要把 Markdown 格式的内容解析为 HTML.

于是使用 marked 完成该操作.

但是默认解析出来的内容很丑,所以需要再渲染一下.

下面三种引入方式主要是渲染样式的使用方式不同.

按渲染方式分,方式一和方式二都是使用 marked 自己的功能实现的.但是方式三只是粗暴地用 css 覆盖了默认样式.

方式一对每个展示的 Vue 文件都需要引入一次样式,而方式二和方式三用了 main.js 引入的方式实现了全局样式.但是方式二只能全局,方式三则用 CSS 覆盖实现了自定义样式.

以引入渲染样式 github-markdown.css 为例.

方式一

单个 Vue 文件即可实现.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//index.vue
//只需要这个文件
<template>
<div class="post">
<div class="title">
<h2>{{this.article.title}}</h2>
</div>
<div class="container">
<div class="markdown-body">
<div v-html="complileMarkdow" v-highlight></div>
</div>
</div>
</div>
</template>

<script type="text/ecmascript-6">
import marked from "marked";
// 这里引入想要的样式
import "../../../node_modules/github-markdown-css/github-markdown.css";
let renderMd = new marked.Renderer();
marked.setOptions({
renderer: renderMd,
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
// 引入样式
highlight: function(code) {
return require("highlight.js").highlightAuto(code).value;
}
});

export default {
components: {
},
data() {
return {
article: {
content: "加载中..."
}
};
},
computed: {
complileMarkdow() {
return marked(this.article.content, { sanitize: true });
}
},
created: function() {
this.$ajax({
url: "/api/article/id",
method: "get",
params: {
id: this.$route.params.id
}
}).then(res => {
if (res.status === 200) {
this.article = res.data;
} else {
//报错
}
});
}
};
</script>

<style scoped >
.post .title {
margin-top: 50px;
text-align: center;
font-size: 24;
}
</style>

方式二

方式二,方式三都需要三个文件.

方式二是全局定义渲染样式.

方式三可以覆盖全局渲染样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// index.vue
<template>
<div class="post">
<div class="title">
<h2>{{this.article.title}}</h2>
</div>
<div class="container">
<div class="markdown-body">
<div v-html="complileMarkdow" v-highlight></div>
</div>
</div>
</div>
</template>

<script type="text/ecmascript-6">
import marked from "marked";
不用下面这种引入样式了
//import "../../../node_modules/github-markdown-css/github-markdown.css";
let renderMd = new marked.Renderer();
marked.setOptions({
renderer: renderMd,
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
// 这个配置实际放到 highlight.js,然后在 main.js 引入
//highlight: function(code) {
// return require("highlight.js").highlightAuto(code).value;
//}
});

export default {
components: {
},
data() {
return {
article: {
content: "加载中..."
}
};
},
computed: {
complileMarkdow() {
return marked(this.article.content, { sanitize: true });
}
},
created: function() {
this.$ajax({
url: "/api/article/id",
method: "get",
params: {
id: this.$route.params.id
}
}).then(res => {
if (res.status === 200) {
this.article = res.data;
} else {
//报错
}
});
}
};
</script>

<style scoped >
.post .title {
margin-top: 50px;
text-align: center;
font-size: 24;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// highlight.js
import Hljs from 'highlight.js'

// 这里引入css
import 'highlight.js/styles/github.css'

let HighLight = {};

HighLight.install = function (Vue) {
Vue.directive('highlight', function (el) {
let blocks = el.querySelectorAll('pre code');
blocks.forEach((block) => {
Hljs.highlightBlock(block)
})
});
}

export default HighLight;
1
2
3
4
5
6
// main.js
...
// highlight.js 路径相应更改
import HighLight from '@/utils/highlight.js'
Vue.use(HighLight);
...

方式三

在 highlight.js 中定义的实际上是全局的 Markdown 解析样式,如果其他地方需要自定义渲染样式,引入 Vue 就行…

其余配置 同 方式二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// index.vue
<template>
<div class="post">
<div class="title">
<h2>{{this.article.title}}</h2>
</div>
<div class="container">
<div class="markdown-body">
<div v-html="complileMarkdow" v-highlight></div>
</div>
</div>
</div>
</template>

<script type="text/ecmascript-6">
import marked from "marked";
不用下面这种引入样式了
//import "../../../node_modules/github-markdown-css/github-markdown.css";
let renderMd = new marked.Renderer();
marked.setOptions({
renderer: renderMd,
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
// 这个配置实际放到 highlight.js,然后在 main.js 引入
//highlight: function(code) {
// return require("highlight.js").highlightAuto(code).value;
//}
});

export default {
components: {
},
data() {
return {
article: {
content: "加载中..."
}
};
},
computed: {
complileMarkdow() {
return marked(this.article.content, { sanitize: true });
}
},
created: function() {
this.$ajax({
url: "/api/article/id",
method: "get",
params: {
id: this.$route.params.id
}
}).then(res => {
if (res.status === 200) {
this.article = res.data;
} else {
//报错
}
});
}
};
</script>

<style scoped >
// 引入 样式
@import "../../../node_modules/github-markdown-css/github-markdown.css";
.post .title {
margin-top: 50px;
text-align: center;
font-size: 24;
}
</style>
loadDisqus