簡體   English   中英

使用 Vite 在 Vue 3 中進行動態布局

[英]Dynamic layout in Vue 3 with Vite

Vue 和 Vite 的新手,但試圖讓動態布局在這里正常工作。 我相信我有需要的東西,但 meta 的問題似乎總是以空 object 或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的屬性。

就此而言,我似乎無法在第一次加載時或在導航欄(只是路由器鏈接)中單擊任何鏈接時正確應用他的布局。

主要問題是layout被初始化為markRaw() ,它不是反應式ref

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

解決方案

  1. layout初始化為ref
  2. 與其查看完整的route對象, route.meta?.layout查看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 }
)

演示

托尼的解決方案很棒。 但是您需要在手表內部添加 computed ,因為它會阻止第一個初始化的“布局”變量的代碼執行,該變量仍未定義,並且會導致不必要的渲染。 因此,請將計算出的 function 添加到 watch function 中。此外,您需要查看“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)
    }
  }
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM