Vue 3中的动态布局与Vite

dohp0rv5  于 2023-01-14  发布在  Vue.js
关注(0)|答案(2)|浏览(251)

新的Vue和Vite,但试图让动态布局在这里正常工作。我相信我有什么是需要的,但问题是,它的 meta似乎总是出现作为一个空对象或undefined

应用程序布局版本

<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>

应用程序版本

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

每个路由都有相应的 meta集,元集具有名为layout的属性。
我只是似乎不能得到他的布局应用正确的第一次加载或任何点击一个链接在导航栏(这只是路由器链接)为此事。

q8l4jmvw

q8l4jmvw1#

主要问题是layout被初始化为markRaw(),而不是被动的ref

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

溶液
1.将layout初始化为ref
1.与其观察完整的route对象,不如观察route.meta?.layout,因为这是处理程序唯一相关的字段。
1.用markRaw() Package layout的新值,以避免在组件定义上发生React。

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

yruzcnhs

yruzcnhs2#

Tony的解决方案非常好。但是您需要在watch中添加computed,因为它会阻止代码执行初始化的第一个“layout”变量,该变量尚未定义,并且会导致不必要的渲染。因此,请在watch函数中添加computed函数。此外,您需要监视“route.path”,而不是“route. meta?.layout”。

import DefaultLayout from '@/layouts/Default.vue'
import { markRaw, ref } from '@vue/reactivity'
import { computed, watch } from '@vue/runtime-core'
import { useRoute } from 'vue-router'

const layout = ref()
const route = useRoute()

watch(
  computed(() => route.path), async () => {
    let metaLayout = route.meta?.layout

    try {
      const metaLayoutComponent = metaLayout && await import(`./layouts/${metaLayout}.vue`)

      layout.value = markRaw(metaLayoutComponent?.default || DefaultLayout)
    } catch (error) {
      layout.value = markRaw(DefaultLayout)
    }
  }
);

相关问题