vue项目中如何加载markdown作为组件

场景

今天忽然临时接到一个需求:

就是将markdown文件直接在vue项目中进行加载,并正常显示出来。

这......,我知道是可以进行加载markdown文件的。

但是我之前没有做过,答复的是:可以做的,但是这个需要一点时间。

领导:那行,你先调研一下。

简单介绍 vue-markdown-loader

vue-markdown-loader可以将 Markdown 文件转换成Vue组件。

安装 npm i vue-markdown-loader -D

步骤1:在vue.config.js文件中去配置

arduino 复制代码
module.exports = {
  chainWebpack:config=>{
    // 定义一个新的webpack模块规则,命名为md
    config.module.rule('md')
    // 通过.test()方法,指定这个规则应该匹配哪些文件
    // 这个规则将应用于所有以.md结尾的文件,即Markdown文件
      .test(/\.md/)
      // 使用vue-loader来处理Markdown文件
      .use('vue-loader')
      .loader('vue-loader')
      .end()
      // 指定vue-markdown-loader来处理Markdown文件
      .use('vue-markdown-loader')
      // 使用vue-markdown-loader包中的markdown-compiler模块来处理Markdown文件
      .loader('vue-markdown-loader/lib/markdown-compiler')
      // raw: true以原始字符串的形式处理Markdown内容,不进行HTML转义等处理。
      .options({
        raw: true
      })
  }
}

哦豁-项目启动报错

遇见的问题1:SyntaxError: Unexpected token '??='

产生问题的原因:你的node版本是否太低。

在项目中验证是否支持??=,可以验证一下。太低的话升级版本就行

还有一种可能:less-loader或者sass-loader或者其他的包的版本不对。

遇见的问题2: Syntax Error: TypeError: Cannot read property 'styles' of undefined

产生问题的原因:vue-loader的版本太高造成的。

我的项目是webpack的版本是:webpack5,它对应的vue-loader应该是vue-loader15

我将它降级为:vue-loader@15

步骤2:在使用的页面

xml 复制代码
<template>
  <div>
    <showMarkdown></showMarkdown>
  </div>
</template>
<script>
// 引入的
import showMarkdown from './biji.md'
export default {
  components:{
    showMarkdown
  },
  data() {
    return {
    
    }
  }
}
</script>

发现问题:优化样式

我们需要下载 github-markdown-css

npm i github-markdown-css -S

这个是用来优化markdown展示出来的样式

能够保持与GitHub相同的视觉效果

在需要的文件中引入 import 'github-markdown-css';

然后我们在组件的父级使用markdown-body这个类来美化markdown

xml 复制代码
<template>
  <div>
    <div class="markdown-body">
      <showMarkdown></showMarkdown>
    </div>
  </div>
</template>

<script>
import 'github-markdown-css';
import showMarkdown from './biji.md'
export default {
  components:{
    showMarkdown
  }
}
</script>

可以把markdown文件在路由中引入吗?

有的小伙伴说:既然我们能够在页面中引入当成组件

那可以在路由文件中引入嘛?

回答:可以的。下面我们就来看下

javascript 复制代码
const routes = [
  {
    path: '/',
    name: 'Home',
    component: ()=>import("../views/echarts.vue")
  },
  {
    path: '/xuexi',
    name: 'xuexi',
    component: ()=>import("../views/xuexi.vue")
  },
  {
    path: '/md',
    name: 'md',
    // 引入的md文件
    component: ()=>import("../views/biji.md")
  },
]
const router = new VueRouter({
  mode: 'hash',
  base: process.env.BASE_URL,
  routes
})

main.js中引入 'github-markdown-css';

javascript 复制代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
//全局引入
import 'github-markdown-css';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false

Vue.use(ElementUI);
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

app.vue使用样式

xml 复制代码
<template>
  <div id="app" class="markdown-body">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/echarts">echarts</router-link> |
      <router-link to="/art">art</router-link> |
      <router-link to="/test">test</router-link> |
      <router-link to="/xuexi">xuexi</router-link> |
    </div>
    <router-view/>
  </div>
</template>

发现问题:markdown-body 污染了全局样式

我们发现这样整个项目中都有 markdown-body 这个类了。

这样会影响其他组件的布局样式。

我们只想在引入的文件是md才有这个样式。

其他的文件没有这个样式。

这个是否我们可以在app.vue文件中判断是否是md文件。

如果是md文件我们添加上markdown-body这个类,否则移除。

我们在路由文件中的meta属性来判断是否是md文件类型。

路由文件

javascript 复制代码
const routes = [
 {
    path: '/md',
    name: 'md',
    component: ()=>import("../views/biji.md"),
    meta:{
      fileType:'md'
    }
  },
  {
    path: '/amd',
    name: 'amd',
    component: ()=>import("../views/amd.md"),
    meta:{
      fileType:'md'
    }
  }
]

app.vue

xml 复制代码
<template>
  <div id="app" :class="componentPathName=='md' ? 'markdown-body' : null">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/echarts">echarts</router-link> |
      <router-link to="/art">art</router-link> |
      <router-link to="/test">test</router-link> |
      <router-link to="/xuexi">xuexi</router-link> |
    </div>
    <router-view/>
  </div>
</template>
<script>
 export default {
  computed: {
    componentPathName () {
      return this.$route.meta && this.$route.meta.fileType
    }
  },
 }
</script>

md文件内容有些时候是从服务端获取的

上面我们渲染的都是本地的文件。

如果 markdown 的内容是从服务端获取的。

动态渲染怎么去处理呢?

我们需要下载 vue-markdown

npm install vue-markdown --save

然后在vue.config.js文件中去配置,与上面的配置相同(一样的哈)

vue-markdown

它允许在Vue应用中轻松展示Markdown格式的内容。

它支持标准的Markdown语法。

如标题、列表、链接、图片、代码块等,并能够将Markdown文本解析为HTML格式。

从而在Vue组件中展示。

vue-markdown 的简单使用

xml 复制代码
<template>
  <div>
    <VueMarkdown>
     {{ mdCont }}
    </VueMarkdown>
  </div>
</template>

<script>
import VueMarkdown from 'vue-markdown';
export default {
  components:{
    VueMarkdown
  },
  data() {
    return{
      mdCont:'#### 绘制一个矩形的思路我们这里绘制矩形\n会使用到canvas.strokeRect(x,y, w, h)方法绘制一个描边矩形![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/91e6190a5cdf4b548cbb7db766acb01c~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oiR55qEZGl25Lii5LqG6IK_5LmI5Yqe:q75.awebp?rk3s=f64ab15b&x-expires=1733213069&x-signature=IKnUtvo%2BDHC8WjX6jKrYtyIUmVA%3D)'
    }
  }
}
</script>

远端请求的内容为啥渲染失败

xml 复制代码
<template>
  <div>
    <VueMarkdown>
     {{ mdCont }}
    </VueMarkdown>
  </div>
</template>

<script>
import VueMarkdown from 'vue-markdown';
export default {
  components:{
    VueMarkdown
  },
  data() {
    return{
      mdCont:'', //返回来的内容
      showKey: '0',
    }
  },
  created(){
    this.serveAPi()
  },
  methods:{
    serveAPi(){
      setTimeout(() => {
        this.mdCont = '#### 绘制一个矩形的思路我们这里绘制矩形\n会使用到canvas.strokeRect(x,y, w, h)方法绘制一个描边矩形![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/91e6190a5cdf4b548cbb7db766acb01c~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oiR55qEZGl25Lii5LqG6IK_5LmI5Yqe:q75.awebp?rk3s=f64ab15b&x-expires=1733213069&x-signature=IKnUtvo%2BDHC8WjX6jKrYtyIUmVA%3D)'
        //更新设置这个key值
        this.showKey = new Date().getTime()+ ''
      },400)
    }
  },
}
</script>

我们发现md无法正常渲染,但是直接写在data中的是可以渲染的。

说明返回来的数据,在渲染的时候组件没有重新更新。

我们只需要使用key更新更新一下就行了。

远端请求内容渲染markdown,key更新组件

xml 复制代码
<template>
  <div>
    <!-- 更新渲染这个组件,要不然返回来的数据无法正常渲染 -->
    <VueMarkdown :key="showKey">
     {{ mdCont }}
    </VueMarkdown>
  </div>
</template>

<script>
import VueMarkdown from 'vue-markdown';
export default {
  components:{
    VueMarkdown
  },
  data() {
    return{
      mdCont:'', //返回来的内容
      showKey: '0',
    }
  },
  created(){
    this.serveAPi()
  },
  methods:{
    serveAPi(){
      setTimeout(() => {
        this.mdCont = '#### 绘制一个矩形的思路我们这里绘制矩形\n会使用到canvas.strokeRect(x,y, w, h)方法绘制一个描边矩形![](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/91e6190a5cdf4b548cbb7db766acb01c~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oiR55qEZGl25Lii5LqG6IK_5LmI5Yqe:q75.awebp?rk3s=f64ab15b&x-expires=1733213069&x-signature=IKnUtvo%2BDHC8WjX6jKrYtyIUmVA%3D)'
        //更新设置这个key值
        this.showKey = new Date().getTime()+ ''
      },400)
    }
  },
}
</script>
相关推荐
腾讯TNTWeb前端团队7 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom12 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom12 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom12 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom12 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试