使用 Vite 在 Vue 3 中进行动态布局

Dynamic layout in Vue 3 with Vite

Vue 和 Vite 的新手,但试图让动态布局在这里正常工作。我相信我有需要的东西,但问题是 meta 似乎总是以空对象或 undefined.

的形式出现

AppLayout.vue

<script setup lang="ts">
  import AppLayoutDefault from './stub/AppLayoutDefault.vue'
  import { markRaw, watch } from 'vue'
  import { useRoute } from 'vue-router'

  const layout = markRaw(AppLayoutDefault)
  const route = useRoute()

  console.log('Current path: ', route.path)
  console.log('Route meta:', route.meta)

  watch(
    () => route.meta,
    async (meta) => {
      try {
        const component = await import(`./stub/${meta.layout}.vue`)
        layout.value = component?.default || AppLayoutDefault
      } catch (e) {
        layout.value = AppLayoutDefault
      }
    },
    { immediate: true }
  )
</script>

<template>
  <component :is="layout"> <router-view /> </component>
</template>

App.vue

<script setup lang="ts">
  import AppLayout from '@/layouts/AppLayout.vue'
</script>
<template>
  <AppLayout>
    <router-view />
  </AppLayout>
</template>

每条路线都有适当的元集,其中 属性 称为 layout

我似乎无法在第一次加载时或在导航栏(只是路由器-link)中单击任何 link 时正确应用布局。

主要问题是 layout 被初始化为 markRaw(),这不是反应式 ref:

const layout = markRaw(AppLayoutDefault) // ❌ not reactive

解决方案

  1. layout 初始化为 ref
  2. 与其查看完整的 route 对象,不如查看 route.meta?.layout,因为这是处理程序唯一相关的字段。
  3. markRaw() 包装 layout 的新值以避免对组件定义的反应。
const layout = ref() 1️⃣

watch(
  () => route.meta?.layout as string | undefined, 2️⃣
  async (metaLayout) => {
    try {
      const component = metaLayout && await import(/* @vite-ignore */ `./${metaLayout}.vue`)
      layout.value = markRaw(component?.default || AppLayoutDefault) 3️⃣
    } catch (e) {
      layout.value = markRaw(AppLayoutDefault) 3️⃣
    }
  },
  { immediate: true }
)

demo