涉及组件:vue-markdown、highlight.js、clipboard
完成功能:将数据以markdown格式渲染,代码部分高亮,内容可一键复制
1.安装
//安装vue-markdown依赖
npm install --save vue-markdown
//安装对应样式,若要定制化样式,可以到对应文件中做修改
npm install github-markdown-css
//安装高亮
npm install highlight.js
//安装复制组件
npm install clipboard --save
2.引用
①main.js
//main.js
import 'github-markdown-css/github-markdown.css'
import hljs from "highlight.js";
Vue.prototype.$hljs = hljs;
// 有多种样式可选,也可以到对应文件中定制化
import "highlight.js/styles/atom-one-dark.css";
// 自定义命令v-highlight
Vue.directive("highlight", function(el) {
let blocks = el.querySelectorAll("pre code");
blocks.forEach(block => {
hljs.highlightBlock(block);
});
});
//复制组件引用
import clipboard from 'clipboard'
Vue.prototype.clipboard = clipboard
②CodeCopy.vue
//CodeCopy.vue
<template>
<div class="copy-content">
<!-- 复制按钮 -->
<div
class="copy-btn code-data-copy"
@click="copyMessage"
data-clipboard-action="copy"
:data-clipboard-text="code"
>
<i class="el-icon-document-copy myicon"></i>
</div>
<div v-if="success" class="copy-success-text">copied!</div>
</div>
</template>
<script>
import clipboard from "clipboard";
export default {
data() {
return {
code: null,
success: false,
};
},
methods: {
copyMessage(value) {
let _this = this;
_this.success = false;
let clipboard = new this.clipboard(".code-data-copy");
clipboard.on("success", function (e) {
// this.$message.error("提問不能為空");
_this.success = true;
// setTimeout(() => {
// _this.success = false
// }, 300)
clipboard.destroy(); // 销毁,避免多次点击重复出现
});
clipboard.on("error", function () {
_this.$message.error("複製失敗");
});
},
},
};
</script>
<style lang="less" scoped>
.copy-content {
height: 0px;
}
.icon {
width: 0.8rem;
height: 0.8rem;
fill: rgb(231, 32, 32);
}
.myicon {
font-size: 14px;
color: #c0c4cc;
&:hover {
color: black;
}
}
.copy-btn {
user-select: none;
opacity: 1;
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
border-radius: 3px;
transition: 0.3s;
background: rgba(255, 255, 255, 0.2);
&:active {
background: rgba(253, 253, 253, 0.575);
}
}
.copy-success-text {
font-family: "微软雅黑";
color: green;
position: absolute;
font-size: 12px;
top: 2px;
right: 18px;
font-weight: 500;
animation: successCopy 0.6s ease both 1;
}
</style>
3.使用
//demo.vue
<template>
<div id="demo>
<!--注意div的class为"markdown-body"否则识别不到样式 -->
<!--v-highlight为自定义命令,直接使用即可 -->
<div class="markdown-body"><VueMarkdown v-highlight :source="dataval"></VueMarkdown></div>
</div>
</template>
<script>
import VueMarkdown from "vue-markdown";
import CodeCopy from "./CodeCopy.vue";
export default {
components: {
VueMarkdown,
},
data() {
return {
//从后台获取数据
data: "DDS Security Plugin是一種用於保護DDS通訊的安全機制。它的架構包括以下三個層次:\n\n1. DDS Security Plugin API層:提供了一個API接口,讓DDS應用程序可以訪問DDS Security Plugin。這一層還負責將安全設置應用到DDS中。\n\n2. DDS Security Plugin實現層:實現了DDS Security Plugin API所定義的接口。它包括了一個安全管理器和相關的安全策略、安全驗證、加密解密等功能。在這一層中,安全管理器負責將安全策略應用到DDS中,使得DDS能夠實現安全通訊。\n\n3. 安全策略層:包括了各種安全策略,如加密、授權、驗證等,以實現不同的安全需求。DDS Security Plugin提供了一些預定義的安全策略,同時也支持用戶自定義的安全策略。在這一層中,安全策略定義了如何對DDS進行安全設置,以保護DDS通訊的安全性。",
dataval :"",
};
},
mounted() {
//为解决序号被吞情况 ,第五点其他问题处会说明
this.dataval = this.data.replace(/\. /g, ".");
},
updated() {
this.update();
},
methods: {
update() {
setTimeout(() => {
// 给每一个 markdown-body 加上复制按钮,具体样式可以自己调整
document.querySelectorAll(".markdown-body").forEach((el) => {
// console.log(el)
if (el.classList.contains("code-copy-added")) return;
let ComponentClass = Vue.extend(CodeCopy);
let instance = new ComponentClass();
instance.code = el.innerText;
instance.parent = el;
/* 手动挂载 */
instance.$mount();
el.classList.add("code-copy-added");
el.appendChild(instance.$el);
});
}, 100);
},
},
};
</script>
<style>
</style>
4.经过样式调整,效果如下:
5.其他问题
vue-markdown可能存在某些问题,比如数据中的1. 2. 3. 等标号会被莫名吞掉隐藏。
经观察发现: 这样格式的数据,标号会被隐藏:\n\n1. 空格 ;如:
\n\n1. DDS Security Plugin API層:提供了一個API接口,
讓DDS應用程序可以訪問DDS Security Plugin。這一層還負責將安全設置應用到DDS中。
\n\n2. DDS Security Plugin實現層:實現了DDS Security Plugin API所定義的接口。
解决方案
将返回数据data做replace替换
//将 .空格 替换成 .
this.p = this.data.replace(/\. /g, ".");
最后:
以上方法均来自网络,四处收罗完成需求后在此记录总结。
demo代码并不完整,但复制下来功能可以实现,样式按需调整。