涉及组件: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代码并不完整,但复制下来功能可以实现,样式按需调整。