将Markdown文件通过路由传递给Vue组件。

huangapple go评论97阅读模式
英文:

Pass markdown files to Vue component through router

问题

I'm using VueJS. I have externally generated markdowns, and I want to generate static pages out of them thanks to a vue component. I'm using the vite-plugin-md to convert imported md files into a component.

Working example

Config (vite.config.js)

import Markdown from "vite-plugin-vue-markdown"

The router (index.ts)

  {
    path: "/my_page_1",
    name: "My Page 1",
    component: () => import("@/pages/markdown.vue"),
  }

The component (markdown.vue)

<template>
  <MardownPage/>
</template>

<script lang="ts" setup>
import MardownPage from "@/assets/markdown/my_page_1.md"
</script>

Expected behavior

In the working example, the component is tied to a unique markdown.

I actually want to use the same component for many different markdown pages. I feel the expected way to do this is to have something like the following in the router :

  {
    path: "/my_page_1",
    name: "My Page 1",
    component: () => import("@/pages/markdown.vue"),
    meta: {
      path: "@/assets/markdown/page_1.md",
    },
  },
  {
    path: "/my_page_2",
    name: "My Page 2",
    component: () => import("@/pages/markdown.vue"),
    meta: {
      path: "@/assets/markdown/page_2.md",
    },
  }

Current (non-working) behavior

On the component side, I've written the following

import {useRoute} from "vue-router";
import { defineAsyncComponent } from 'vue';

const route = useRoute();

console.log(route.meta.path);

const AsyncComp = defineAsyncComponent(() =>
  import(route.meta.path)
)

While the path appears in the console, it does return an error related to the dynamic importation of the module (error loading dynamically imported module).

I've tested many options related to lazy loading, dynamic routes, promises, ... (which I'm not 100% familiar and skilled with) but haven't worked my way around to do so.

英文:

I'm using VueJS. I have externally generated markdowns, and I want to generate static pages out of them thanks to a vue component. I'm using the vite-plugin-md to convert imported md files into a component.

Working example

Config (vite.config.js)

import Markdown from &quot;vite-plugin-vue-markdown&quot;

The router (index.ts)

  {
    path: &quot;/my_page_1&quot;,
    name: &quot;My Page 1&quot;,
    component: () =&gt; import(&quot;@/pages/markdown.vue&quot;),
  }

The component (markdown.vue)

&lt;template&gt;
  &lt;MardownPage/&gt;
&lt;/template&gt;

&lt;script lang=&quot;ts&quot; setup&gt;
import MardownPage from &quot;@/assets/markdown/my_page_1.md&quot;
&lt;/script&gt;

Expected behavior

In the working example, the component is tied to a unique markdown.

I actually want to use the same component for many different markdown pages. I feel the expected way to do this is to have something like the following in the router :

  {
    path: &quot;/my_page_1&quot;,
    name: &quot;My Page 1&quot;,
    component: () =&gt; import(&quot;@/pages/markdown.vue&quot;),
    meta: {
      path: &quot;@/assets/markdown/page_1.md&quot;,
    },
  },
  {
    path: &quot;/my_page_2&quot;,
    name: &quot;My Page 2&quot;,
    component: () =&gt; import(&quot;@/pages/markdown.vue&quot;),
    meta: {
      path: &quot;@/assets/markdown/page_2.md&quot;,
    },
  }

Current (non-working) behavior

On the component side, I've written the following

import {useRoute} from &quot;vue-router&quot;;
import { defineAsyncComponent } from &#39;vue&#39;

const route = useRoute();

console.log(route.meta.path);

const AsyncComp = defineAsyncComponent(() =&gt;
  import(route.meta.path)
)

While the path appears in the console, it does return an error related to the dynamic importation of the module (error loading dynamically imported module).

I've tested many options related to lazy loading, dynamic routes, promises, ... (which I'm not 100% familiar and skilled with) but haven't worked my way around to do so.

答案1

得分: 1

根据您目前的内容以及所描述的期望输出,我建议您首先查看defineAsyncComponent。这个函数需要提供一个已解析的Promise。您目前正在尝试在运行时动态导入,并且这可能与路径别名有关。

我设置了以下项目:

vite.config.ts

import { fileURLToPath, URL } from 'node:url';

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import Markdown from 'vite-plugin-vue-markdown';
import path from 'node:path';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue({
      include: [/.vue$/, /.md$/],
    }),
    Markdown(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      'components': path.resolve(__dirname, './src/components'),
    }
  }
})

src/router/index.ts

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    // ...
    {
      path: '/test',
      name: 'test',
      component: () => import('@/views/MarkdownView.vue'),
      meta: {
        path: 'components/Test.md',
        markdownComponent: defineAsyncComponent(() => import('components/Test.md'))
      },
    }
  ]
})

src/views/MarkdownView.vue

<template>
    <AsyncMarkdown />
</template>
<script setup lang="ts">
import { defineAsyncComponent } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();

console.log(route.meta.path) // components/Test.md

// 不起作用
const AsyncMarkdown = defineAsyncComponent(() => import(route.meta.path));

// 起作用
const AsyncMarkdown = route.meta.markdownComponent;
</script>

如果我将route.meta.path更改为相对路径../components/Test.md,它将能够加载组件。

可能的解决方案

  1. 在您的路由器中加载defineAsyncComponent()
  2. 将没有别名的完整/相对路径添加到route.meta.page变量中。
英文:

Looking at what you currently have and what you described as the desired output, I would suggest starting at looking at defineAsyncComponent. This function needs to be provided with a resolved promised. You are currently attempting to run import dynamically at runtime & it might also have something to do with aliases in your path.

I setup the following project:

vite.config.ts

import { fileURLToPath, URL } from &#39;node:url&#39;

import { defineConfig } from &#39;vite&#39;
import vue from &#39;@vitejs/plugin-vue&#39;
import Markdown from &#39;vite-plugin-vue-markdown&#39;
import path from &#39;node:path&#39;

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue({
      include: [/\.vue$/, /\.md$/],
    }),
    Markdown(),
  ],
  resolve: {
    alias: {
      &#39;@&#39;: fileURLToPath(new URL(&#39;./src&#39;, import.meta.url)),
      &#39;components&#39;: path.resolve(__dirname, &#39;./src/components&#39;),
    }
  }
})

src/router/index.ts

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    // ...
    {
      path: &#39;/test&#39;,
      name: &#39;test&#39;,
      component: () =&gt; import(&#39;@/views/MarkdownView.vue&#39;),
      meta: {
        path: &#39;components/Test.md&#39;,
        markdownComponent: defineAsyncComponent(() =&gt; import(&#39;components/Test.md&#39;))
      },
    }
  ]
})

src/views/MarkdownView.vue

&lt;template&gt;
    &lt;AsyncMarkdown /&gt;
&lt;/template&gt;
&lt;script setup lang=&quot;ts&quot;&gt;
import { defineAsyncComponent } from &#39;vue&#39;
import { useRoute } from &#39;vue-router&#39;;

const route = useRoute()

console.log(route.meta.path) // components/Test.md

// DOES NOT WORK
const AsyncMarkdown = defineAsyncComponent(() =&gt; import(route.meta.path))

// WORKS
const AsyncMarkdown = route.meta.markdownComponent
&lt;/script&gt;

If I change the route.meta.path to the relative path ../components/Test.md, it will then load the component.

Possible Solutions

  1. Load the defineAsyncComponent() in your router
  2. Add the full/relative path without alias to the route.meta.page variable.

huangapple
  • 本文由 发表于 2023年3月3日 18:30:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75625920.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定