vue实现.md文件预览功能的两种方法详解

vue3 + vite 实现方案 (vite-plugin-md + github-markdown-css)

配置vite-plugin-md插件:插件详情请参考插件文档

步骤一:安装依赖

npm i vite-plugin-md -D
npm i github-markdown-css

步骤二: vite-plugin-md 插件配置

// vite.config.ts 
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import WindiCSS from 'vite-plugin-windicss'
import Markdown from 'vite-plugin-md'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue({
      include: [/\.vue$/, /\.md$/]
    }),
    WindiCSS(),
    Markdown({
      builders: []
    })
  ],
  resolve: {
    alias: {
      '@': '/src/',
      'vue': 'vue/dist/vue.esm-bundler.js'
    }
  },
})

步骤三: 配置 tsconfig.json, 将md文件加入编译需要处理的文件列表中。

"include": [
    "vite.config.ts",
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "src/**/*.css",
    "src/**/*.md" // md文件
  ],

步骤四: 样式引入与使用

<template>
    <article class="markdown-body"> // 使用article 标签并且设置class
        <FileComMd />
    </article>

</template>
<script>
import 'github-markdown-css'
</script>

步骤五:组件中使用

使用vue组件一样的引入方式,

<template>
    <FileReadMd></FileReadMd>
</template>
<script lang="ts" setup>
import FileReadMd from './FileReadMd.vue'
</script>

对于文档的说明文件,通常需求引入多个md文件,这里提供批量引入方式。

<!--
 * @Description: 说明文档
 * @Author: ym
 * @Date: 2022-11-25 17:12:54
 * @LastEditTime: 2022-11-29 14:20:39
-->
<template>
  <div class="h-full flex flex-col">
    <div class="flex p-2 items-center bg-primary text-white">
      <img src="@/assets/img/logo.png"  />
      <div class="flex-1 px-1 text-[16px]">说明文档</div>
    </div>
    <div class="flex-1 flex overflow-hidden">
      <div class="w-[200px] overflow-y-auto bg-bg">
        <el-menu active-text-color="#464bff" background-color="#f3f6fa" class="bg-bg" :default-active="defaultActive" text-color="#333">
          <template v-for="menu in menuList">
            <el-sub-menu v-if="menu.childrenList && menu.childrenList.length > 0" :index="menu.elementType">
              <template #title>
                <i :class="`${menu.icon} iconfont`"></i>
                <span>{{ menu.name }}</span>
              </template>
              <template v-for="menuItem in menu.childrenList">
                <el-sub-menu v-if="menuItem.childrenList && menuItem.childrenList.length > 0" :index="(menu.elementType || '') + menuItem.type">
                  <template #title>{{ menuItem.name }}</template>
                  <el-menu-item v-for="item in menuItem.childrenList" :index="item.type" @click="getMdFileData(item.type)">{{ item.name }}</el-menu-item>
                </el-sub-menu>
                <el-menu-item v-else :index="menuItem.type" @click="getMdFileData(menuItem.type)">{{ menuItem.name }}</el-menu-item>
              </template>
            </el-sub-menu>
            <el-menu-item v-else :index="menu.elementType" @click="getMdFileData(menu.type)">
              <i :class="`${menu.icon} iconfont`"></i>
              <span>{{ menu.name }}</span>
            </el-menu-item>
          </template>
        </el-menu>
      </div>
      <div class="flex-1 bg-opacity-20 flex px-18 py-10 overflow-y-auto">
        <article class="markdown-body">
          <component v-if="fileName" :is="content" :key="fileName" />
          <div v-else>{{ `${fileName}文档正在维护中...` }}</div>
        </article>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref, shallowRef } from 'vue'
import { menuList } from './graphManage/components/node'
import { useRoute } from 'vue-router'
const route = useRoute()
const fileName = ref('')
const defaultActive = ref('FileReadNode')
route.query.type && (defaultActive.value = route.query.type as string)
const content = shallowRef('')
// 导入document下的所有.md文件
const res = import.meta.glob('../assets/document/*.md', { eager: true })
const getMdFileData = (name?: string) => {
  if (name) {
    // 切换左侧菜单时,右侧动态加载对应组件
    Object.entries(res).forEach(([path, definition]: any) => {
      const componentName = path
        .split('/')
        .pop()
        ?.replace(/\.\w+$/, '')
      if (componentName === name) {
        fileName.value = name
        content.value = definition.default
      }
    })
  }
}
getMdFileData(defaultActive.value)

// 这种方式在本地生效, 测试环境组件加载报错
// const getMdFileData = (name?: string) => {
//   name &&
//     import(/* @vite-ignore */ '../assets/document/' + name + '.md')
//       .then((res) => {
//         content.value = res.default
//         fileName.value = name
//       })
//       .catch((err) => {
//         console.error(err)
//         fileName.value = ''
//       })
// }
</script>

vue2实现方案(vue-markdown + vue-markdown-loader +github-markdown-css)

步骤一: 安装依赖

npm i vue-markdown

npm i vue-markdown-loader github-markdown-css -D

步骤二:vue.config.js 配置loader

module.exports = {
  runtimeCompiler: true,
  css: {
    loaderOptions: {
      scss: {
        prependData: `@import "~@/assets/style/index.scss";`
      }
    }
  },
  chainWebpack: config => {
    config.module
    .rule("md")
    .test(/\.md$/)
    .use("vue-loader")
    .loader("vue-loader")
    .end()
    .use("vue-markdown-loader")
    .loader("vue-markdown-loader/lib/markdown-compiler")
    .options({
      raw: true
    });
  },
}

步骤三: .vue组件中使用

<template>
  <div class="documentView">
    <div class="header">
      <img src="@/assets/logo.png" >
      <img class="bardBg" src="@/assets/bar_bg.png" >
      <div class="title">数据 - 说明文档</div>
    </div>
    <div class="content">
      <div class="left">
        <el-menu class="menu">
          <template v-for="type in menuList">
            <el-submenu v-if="type.childrenList && type.childrenList.length > 0" :index="type.type" :key="type.key">
              <template #title>
                <i :class="type.icon + ' iconfont'"></i>
                <span>{{ type.text }}</span>
              </template>
              <template v-for="menuItem in type.childrenList">
                <el-submenu class="menuSub" v-if="menuItem.childrenList && menuItem.childrenList.length > 0" :key="menuItem.key" :index="menuItem.key">
                  <template #title>{{ menuItem.text }}</template>
                  <el-menu-item @click="getMdFileData(lastMenu.key)" :index="lastMenu.path" v-for="lastMenu in menuItem.childrenList" :key="lastMenu.key">{{
                  lastMenu.text
                }}</el-menu-item>
                </el-submenu>
                <el-menu-item v-else :key="menuItem.key" :index="menuItem.path" @click="getMdFileData(menuItem.key)">{{ menuItem.text }}
                </el-menu-item>
              </template>
            </el-submenu>
            <el-menu-item v-else :index="type.type" :key="type.key" @click="getMdFileData(menuItem.key)">
              <el-icon size="20" :class="type.icon  + ' iconfont'"></el-icon>
              <span>{{ type.text }}</span>
            </el-menu-item>
          </template>
        </el-menu>
      </div>
      <div class="markdown-body right">
        <vueMarkDown v-if="mdData" :source="mdData"></vueMarkDown>
        <div v-else>{{`${type}算子文档正在维护中...`}}</div>
      </div>
    </div>
  </div>
</template>
<script>
import vueMarkDown from "vue-markdown"
import axios from 'axios'
import 'highlight.js/styles/github.css'
import 'github-markdown-css' // 使用github样式
import { menuConfig } from '@/utils/menu.js'
export default {
  name: 'DocumentView',
  components: { vueMarkDown },
  data () {
    return {
      mdData: '',
      menuList: menuConfig,
      type: ''
    }
  },
  methods: {
    async getMdFileData (key) {
      this.type = key
      const url_ = `document/${key}.md` // *文明位于项目的public下
      try {
        const res = await axios.get(url_)
        this.mdData = res.data
      } catch (error) {
        this.$message(this.type + '文档维护中...')
        console.log('缺少文档', this.type)
        this.mdData = ''
      }
    }
  },
  mounted () {
    this.getMdFileData(this.$route.query.type)
  }
}
</script>

到此这篇关于vue实现.md文件预览功能的两种方法详解的文章就介绍到这了,更多相关vue预览.md文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源链接:https://www.jb51.net/javascript/339444xl6.htm

© 版权声明
THE END
支持一下吧
点赞7 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容