• 【vue+marked】marked


    一、使用marked

    第一步:下载marked和代码块高亮highlight.js

    1. npm i marked
    2. npm i highlight.js
    3. npm i markdown-loader
    4. npm i github-markdown-css

    第二步:注册并使用

    main.js

    1. import hljs from "highlight.js";
    2. import "github-markdown-css";
    3. import "highlight.js/styles/atom-one-dark.css";
    4. Vue.directive("highlight", function (el) {
    5. let blocks = el.querySelectorAll("pre code");
    6. blocks.forEach((block) => {
    7. hljs.highlightBlock(block);
    8. });
    9. });

    页面内使用

    1、其中class的markdown-body是必须要带的,marked的样式,同时如果需要修改样式,也可以通过此修改

    2、v-highlight全局注册代码块高亮

    3、自定义渲染器我是需要改变标题转换,如果你们有需要可以自行处理

    1. <template>
    2. <div id="Mindopt" class="Mindopt">
    3. <div v-highlight class="replybox markdown-body" v-html="Mindoptinfo">div>
    4. div>
    5. template>
    6. <script>
    7. // 创建自定义渲染器
    8. class CustomRenderer extends marked.Renderer {
    9. heading (text, level) {
    10. // 将一级标题转换为h1标签
    11. if (level === 1) {
    12. return `

      # ${text}

      `
      ;
    13. } else if (level === 2) {
    14. return `

      ## ${text}

      `
      ;
    15. } else if (level === 3) {
    16. return `

      ### ${text}

      `
      ;
    17. } else if (level === 4) {
    18. return `

      #### ${text}

      `
      ;
    19. } else if (level === 5) {
    20. return `
      ##### ${text}
      `
      ;
    21. } else if (level === 6) {
    22. return `
      ###### ${text}
      `
      ;
    23. }
    24. }
    25. // text (text) {
    26. // console.log(text);
    27. // }
    28. // code (code, language, isEscaped) {
    29. // console.log(language);
    30. // if (language && language === 'math') {
    31. // return katex.renderToString(code, { throwOnError: false });
    32. // }
    33. // return marked.Renderer.prototype.code.call(renderer, code, language, isEscaped);
    34. // };
    35. }
    36. // 使用自定义渲染器
    37. const renderer = new CustomRenderer();
    38. const markedOptions = {
    39. renderer: renderer,
    40. breaks: true,
    41. };
    42. import { marked } from "marked";
    43. import { getoptInfo, getGroupMessage, updataGroup, deleteGroupMessages } from '@/api/Mindopt'
    44. export default {
    45. name: 'Mindopt',
    46. data () {
    47. return {
    48. Mindoptinfo: '',
    49. }
    50. },
    51. created () {
    52. this.getoptInfo()
    53. },
    54. methods: {
    55. // 获取信息
    56. async getoptInfo () {
    57. const res = await getoptInfo()
    58. this.Mindoptinfo = res.data
    59. this.Mindoptinfo = marked(this.Mindoptinfo, markedOptions);
    60. },
    61. }
    62. }
    63. script>
    64. <style lang="scss">
    65. // 回答的格式或者数据回显的格式
    66. .markdown-body {
    67. // font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
    68. // Microsoft YaHei, Arial, sans-serif !important;
    69. // line-height: 20px;
    70. // & ul {
    71. // list-style: none;
    72. // padding-left: 20px;
    73. // }
    74. color: #000 !important;
    75. p {
    76. margin-top: 10px !important;
    77. margin-bottom: 10px !important;
    78. }
    79. pre {
    80. padding: 5px !important;
    81. margin-bottom: 10px !important;
    82. }
    83. .hljs {
    84. color: #abb2bf;
    85. background: #282c34;
    86. }
    87. .hClass {
    88. //出现#则不转换为h1等标签
    89. font-size: 16px;
    90. color: #8a2328;
    91. font-weight: 600;
    92. margin: 10px 0;
    93. }
    94. /* 只改变普通 code 标签的颜色,不影响 pre 中的 code */
    95. code:not(pre) {
    96. color: red;
    97. font-weight: 600;
    98. background-color: rgba(175, 184, 193, 0.3);
    99. margin: 0 5px;
    100. }
    101. a {
    102. color: #1d71f7 !important;
    103. }
    104. }
    105. style>

    二、代码块和块引用添加复制按钮

    页面使用

    1. <template>
    2. <div id="Mindopt" class="Mindopt">
    3. <div v-highlight class="replybox markdown-body" v-html="Mindoptinfo">div>
    4. div>
    5. template>
    6. <script>
    7. import CodeCopy from './CodeCopy.vue'
    8. export default {
    9. name: 'Mindopt',
    10. data () {
    11. return {
    12. Mindoptinfo: '',
    13. }
    14. },
    15. updated () {
    16. this.update()
    17. },
    18. methods: {
    19. //获取对应markdown代码块标签
    20. update () {
    21. setTimeout(() => {
    22. // 代码块添加复制按钮
    23. document.querySelectorAll('pre').forEach(el => {
    24. // console.log(el)
    25. if (el.classList.contains('code-copy-added')) return
    26. // https://cn.vuejs.org/v2/api/index.html#Vue-extend
    27. /* 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象 */
    28. let ComponentClass = Vue.extend(CodeCopy)
    29. let instance = new ComponentClass()
    30. instance.code = el.innerText
    31. instance.parent = el
    32. /* 手动挂载 */
    33. instance.$mount()
    34. el.classList.add('code-copy-added')
    35. el.appendChild(instance.$el)
    36. })
    37. // 块引用添加复制按钮
    38. document.querySelectorAll('blockquote').forEach(el => {
    39. // console.log(el)
    40. if (el.classList.contains('code-copy-added')) return
    41. // https://cn.vuejs.org/v2/api/index.html#Vue-extend
    42. /* 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象 */
    43. let ComponentClass = Vue.extend(CodeCopy)
    44. let instance = new ComponentClass()
    45. instance.code = el.innerText
    46. instance.parent = el
    47. /* 手动挂载 */
    48. instance.$mount()
    49. el.classList.add('code-copy-added')
    50. el.appendChild(instance.$el)
    51. })
    52. }, 100)
    53. },
    54. }
    55. }
    56. script>
    57. <style lang="scss">
    58. // 复制按钮
    59. .codeContent {
    60. max-width: 400px;
    61. margin: 0 auto;
    62. padding-top: 25vh;
    63. }
    64. .code-copy-added {
    65. background-color: #282c34;
    66. color: white;
    67. padding: 25px 20px;
    68. margin: 10px 0;
    69. text-align: left;
    70. border-radius: 3px;
    71. position: relative;
    72. }
    73. .code-copy-added:hover .copy-btn {
    74. opacity: 1;
    75. }
    76. style>

    CodeCopy.vue

    1. <template>
    2. <div class="copy-content">
    3. <div
    4. class="copy-btn code-data-copy"
    5. @click="copyMessage"
    6. data-clipboard-action="copy"
    7. :data-clipboard-text="code"
    8. >
    9. 复制
    10. div>
    11. div>
    12. template>
    13. <script>
    14. import Clipboard from 'clipboard' //复制插件
    15. export default {
    16. data () {
    17. return {
    18. code: null,
    19. // success: false
    20. }
    21. },
    22. methods: {
    23. copyMessage (value) {
    24. let _this = this
    25. // _this.success = false
    26. let clipboard = new Clipboard('.code-data-copy')
    27. clipboard.on('success', function (e) {
    28. _this.$message.success('复制成功')
    29. // _this.success = true
    30. // setTimeout(() => {
    31. // _this.success = false
    32. // }, 300)
    33. clipboard.destroy() // 销毁,避免多次点击重复出现
    34. })
    35. clipboard.on('error', function () {
    36. console.log('复制失败')
    37. })
    38. }
    39. }
    40. }
    41. script>
    42. <style lang="scss" scoped>
    43. .copy-content {
    44. height: 0;
    45. // position: absolute;
    46. // top: 0;
    47. // right: 0;
    48. }
    49. .icon {
    50. width: 0.8rem;
    51. height: 0.8rem;
    52. fill: white;
    53. }
    54. .copy-btn {
    55. user-select: none;
    56. opacity: 0;
    57. position: absolute;
    58. right: 5px;
    59. top: 5px;
    60. cursor: pointer;
    61. padding: 5px;
    62. border-radius: 3px;
    63. transition: 0.3s;
    64. // background: rgba(255, 255, 255, 0.2);
    65. background: #fff;
    66. &:active {
    67. // background: rgba(253, 253, 253, 0.575);
    68. background: rgba(253, 253, 253, 0.575);
    69. }
    70. }
    71. .copy-success-text {
    72. color: white;
    73. position: absolute;
    74. font-size: 12px;
    75. top: 8px;
    76. right: 2.5rem;
    77. font-weight: 200;
    78. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
    79. Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    80. animation: successCopy 0.5s ease both 1;
    81. }
    82. @keyframes successCopy {
    83. 70% {
    84. opacity: 1;
    85. transform: scale(1);
    86. }
    87. 100% {
    88. opacity: 0;
    89. transform: scale(0.5);
    90. }
    91. }
    92. style>

  • 相关阅读:
    【每日刷题】Day66
    烧写最小linux失败,开机显示Wrong Ramdisk Image Format
    JSX看着一篇足以入门
    openlayers 绘制动态迁徙线、曲线
    《元宇宙2086》亮相金鸡奖中国首部元宇宙概念院线电影启动
    国际版阿里云腾讯云免费开户:服务器怎样转移
    机器学习 day36(纯度)
    JAVA 直连数据库连接
    Qt字符串生成二维码功能
    【技术积累】Vue.js中的核心知识【三】
  • 原文地址:https://blog.csdn.net/Qxn530/article/details/140997694