如何在自定义 404 页面中使用布局?

问题描述 投票:0回答:1

我在我的一个项目中使用 Nuxt 3 并为其创建了一个 404 页面。我的项目中有两个布局。我的默认布局(default.vue)包括页脚和页眉等常规组件。在我的自定义 404 页面中,我想使用默认布局(default.vue)。

但是,当我定义我的 404 组件时,如下所示:

<script setup>
    const error = useError();

    console.log({error})

    const handleError = () => {
        clearError({
            redirect: '/',
        });
    };
</script>

<template>
    <NuxtLayout>
        <div class="prose">
            <h1>Dang</h1>
            <p>
                <strong>{{ error.message }}</strong>
            </p>
            <p>It looks like something broke.</p>
            <p>Sorry about that.</p>
            <p>
                Go back to your 
                <a @click="handleError">
                dashboard.
                </a>
            </p>
        </div>
    </NuxtLayout>
</template>

由于标头组件中使用了 prop,我收到错误。

无法读取未定义的属性(读取“modeCheckout”)

这是我的代码:

布局/default.vue

<script setup>
  import {inject,watch} from 'vue';
  const { alert, setAlert } = inject('alert')
</script>


<template>
  <div class="page-wrapper">
    <div class="content-wrapper" >
      <Alert :alert="alert"/>
      <AppBar/>
      <div class="main-wrapper">
        <slot></slot>
      </div>
      <WebsiteFooter/>
    </div>
  </div>
</template>
<style lang="scss">
.page-wrapper{
  @include d-flex(row,flex-start,flex-start);
  min-height: 100%;
  .content-wrapper{
    width: 100%;
    height: 100%;
    .main-wrapper{
      margin-top: 10px;
      border-radius: 4px;
      padding: 16px;
    }
  }
}
</style>

AppBar.vue

<script setup>
  import {ref,inject} from 'vue';
  const props = defineProps({
    modeCheckout:{type:Boolean,default:false}
  })

  const isClickedHamMenu = ref(false);
  const {basketItemCount} = inject('basketItemCount')

  const toggleMenu = () =>{
    isClickedHamMenu.value = !isClickedHamMenu.value
    let menu = document.querySelector('.menu-wrapper');

    if(isClickedHamMenu.value){
      menu.classList.add('slide-menu-ttb');
      if(menu.classList.contains('slide-menu-btt')){
        menu.classList.remove('slide-menu-btt')
      }
    }
    else{
      menu.classList.add('slide-menu-btt');
      if(menu.classList.contains('slide-menu-ttb')){
        menu.classList.remove('slide-menu-ttb')
      }
      setTimeout(()=>{
        menu.classList.remove('slide-menu-btt');
      },150)
    }
  }
</script>
<template>
  <div class="container">
    <div class="app-bar-wrapper p10">
      <NuxtLink class="logo-wrapper" to="/">
        <img src="/logo.png" alt="Artisan">
      </NuxtLink>
      <div v-if="!props.modeCheckout" class="search-wrapper">
        <Icon name="mdi:magnify" color="black" size="24"/>
        <input type="text" autocomplete="off" spellcheck="false" placeholder="Search">
      </div>
      <div class="app-bar-actions">
        <div v-if="!props.modeCheckout" :class="['hamburger-wrapper', isClickedHamMenu ? 'close' : '']" @click="toggleMenu">
          <span class="child-1"></span>
          <span class="child-2"></span>
          <span class="child-3"></span>
        </div>
        <div class="icon-wrapper">
          <Button
            icon="mdi:account"
            fontSize="24px"
            fontColor="#000"
            text
            hoveredBackground="transparent"
            background="transparent"
            hoveredColor="#000"
            padding="0"
          />
        </div>
        <NuxtLink to="/cart" class="icon-wrapper">
          <Button
            icon="mdi:cart-outline"
            fontSize="24px"
            fontColor="#000"
            text
            hoveredBackground="transparent"
            background="transparent"
            hoveredColor="#000"
            padding="0"
          />
          <div  v-if="basketItemCount>0" class="cart-item-count">
            {{basketItemCount}}
          </div>
        </NuxtLink>
      </div>
    </div>
    <Menu v-if="!props.modeCheckout"/>
  </div>
</template>

应用程序.vue

<script setup>
import {ref} from 'vue'
  const alert = ref({});
  const basketItemCount = ref(0)
  const route = useRoute()

  const setAlert = obj => {
    alert.value = obj;
  }

  const setBasketItemCount = () =>{
    basketItemCount.value = JSON.parse(window.localStorage.getItem('basket-items'))?.reduce((a,b)=>a+b.quantity,0) || 0
  }

  onMounted(() => {
    setBasketItemCount();
  })

  provide('basketItemCount',{basketItemCount,setBasketItemCount})
  provide('alert', {alert,setAlert});
</script>

<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>
vue.js vuejs3 nuxt3.js
1个回答
0
投票

在Nuxt 3中,您可以通过在layouts目录中定义error.vue文件来创建自定义404页面。该文件将用作错误页面(包括 404 页面)的默认布局。 文档

设置方法如下:

创建一个layouts/error.vue文件:这将成为所有错误页面的布局。

为404错误添加自定义逻辑:在layouts/error.vue中,您可以检查error.statusCode并根据它有条件地渲染内容。

// layouts/error.vue
<template>
  <div>
    <h1 v-if="error?.statusCode === 404">Page Not Found</h1>
    <p v-else>Oops, something went wrong.</p>
    <!-- Additional layout components or links can go here -->
  </div>
</template>

<script setup>
defineProps({
  error: Object
})
</script>

通过此设置,Nuxt 3 将使用 error.vue 来处理任何错误,并且 statusCode 检查可让您专门针对 404 错误自定义内容。

© www.soinside.com 2019 - 2024. All rights reserved.