Vue2实现markdown语法支持,代码高亮,显示行号,复制功能
涉及组件:
vue-markdown
、highlight.js
、highlight-line-numbers
、clipboard
完成功能:将数据以
markdown格式渲染
,代码部分高亮
,代码显示行号
,代码可一键复制
1.依赖安装
// 安装vue-markdown依赖
npm install vue-markdown
// 安装高亮
npm install highlight.js
// 安装代码行显示
npm install hightlight-line-numbers.js
// 安装复制组件
npm install clipboard --save
2.highligh
①highlight-plugin.js插件
import Vue from 'vue';
import Hljs from 'highlight.js'
import 'highlight.js/styles/stackoverflow-dark.css' // 样式文件
let Highlight = {};
Highlight.install = function(Vue, options) {
Vue.directive('highligh', function(el) {
let blocks = el.querySelectorAll('pre code');
blocks.forEach((block, index) => {
/** 代码高亮 */
Hljs.highlightBlock(block);
/** 手动添加一个hljs类名,防止不支持的语言背景变空白 */
block.classList.add('hljs');
})
})
}
export default Highlight;
②main.js
// 引入使代码行高亮的插件
import Highlight from "./plugins/highlight-plugin"
// 引入vue-markdown
import VueMarkdown from "vue-markdown"
import Vue from "vue";
// 将vue-markdown注册为全局组件
Vue.component("vue-markdown", VueMarkdown)
Vue.use(Highlight);
3.使用指令
在需要
支持markdown
语法的组件中使用即可,文章以search.vue
为例其中
source
属性为md语法的内容,将内容传进组件会自动转换为html
并显示在页面,此时已经实现页面支持md
语法,且代码块高亮也支持,效果如下。接下来将实现代码行号显示
、语言显示
和复制代码
<template>
<vue-markdown :source="item.content" v-highlight>
</vue-markdown>
</template>
<script>
</script>
4.行号显示
在
highlight-plugin.js
插件下将highlight-line-numbers
引入,并新增一行代码将行号显示。
import Vue from 'vue';
import Hljs from 'highlight.js'
import 'highlight.js/styles/stackoverflow-dark.css' // 样式文件
import 'highlight-line-numbers'
let Highlight = {};
Highlight.install = function(Vue, options) {
Vue.directive('highligh', function(el) {
let blocks = el.querySelectorAll('pre code');
blocks.forEach((block, index) => {
/** 代码高亮 */
Hljs.highlightBlock(block);
/** 手动添加一个hljs类名,防止不支持的语言背景变空白 */
block.classList.add('hljs');
/** 显示行号 **/
Hljs.lineNumbersBlock(block);
})
})
}
export default Highlight;
但是页面并没有出现对应的行号显示,且控制台显示
highligh not...
的错误,因为highlight-line-numbers默认自动执行,因此,需要对该代码进行修改。
将highlight-line-numbers.js
里的代码全选复制新建文件,修改如下
function lineNumberInit(hljs, w, d) {
// jshint multistr:true
xxxx原代码内容
export { lineNumberInit }
if (hljs) {
hljs.initLineNumbersOnLoad = initLineNumbersOnLoad;
hljs.lineNumbersBlock = lineNumbersBlock;
hljs.lineNumbersValue = lineNumbersValue;
addStyles();
} else {
w.console.error("highlight.js not detected!");
}
- 在
highlight-plugin.js
文件下引入该文件,并修改代码
// highlight.js
import Vue from 'vue'
import Hljs from 'highlight.js'
import 'highlight.js/styles/stackoverflow-dark.css'
import { lineNumberInit } from "../utils/highlight-line-numbers.js";
lineNumberInit(Hljs, window, window.document);
let Highlight = {}
Highlight.install = function (Vue, options) {
Vue.directive('highlight', function (el) {
let blocks = el.querySelectorAll('pre code');
blocks.forEach((block, index) => {
/** 代码高亮 */
Hljs.highlightBlock(block);
/** 手动添加一个hljs类名,防止不支持的语言背景变空白 */
block.classList.add('hljs');
/** 从这开始是设置行号 */
Hljs.lineNumbersBlock(block);
})
})
}
export default Highlight
此时,代码块成功实现行号显示。
5.copy
在
search.vue
中引入clipboard
实现复制功能。要实现代码
语言显示
和复制功能
的前置条件,必须要有对应的元素进行展示。此处,选择操作DOM
元素的方式在代码块元素pre
之前创建对应的元素进行展示。代码如下:
<template>
<vue-markdown :source="item.content" v-highlight v-copy>
</vue-markdown>
</template>
<script>
import Clipboard from "clipboard";
export default {
created() {
// 在 created 钩子函数中定义全局变量 clipboard
let clipboard = new Clipboard(".copy-btn");
clipboard.on("success", e => {
this.$message(messageCreate("success", "复制成功"));
e.clearSelection();
});
clipboard.on("error", e => {
this.$message(messageCreate("error", "复制失败"));
});
},
directives: {
inserted(el) {
let blocks = el.querySelectorAll("pre");
blocks.forEach(block => {
let code = block.querySelector("code");
let div = document.createElement("div");
let span = document.createElement("span");
span.innerHTML = getLanguage(code.className);
div.appendChild(span);
div.classList.add("btn-copy");
let button = document.createElement("button");
button.setAttribute("data-clipboard-text", code.innerText);
button.innerText = "复制";
div.appendChild(button);
button.classList.add("copy-btn");
block.parentNode.insertBefore(div, block);
});
}
}
}
</script>
最终效果
此时,已经成功实现了代码的高亮、行号、语言、复制代码功能。