Skip to content

自定义404页面

自定义404页面

image-20250414204228477

目录

[toc]

背景

逛掘金发现了一个很酷的 404 页面,于是想在自己的博客也搞一个,正好 VitePress 也支持自定义 404 页面的内容,可以根据官方提供的not-found插槽去配置即可,在自定义的 docs/.vitepress/theme/index.ts 文件中去配置就行。

版权

警告

本着开源共享、共同学习的精神:

本文是在 《Hyde Blog》博主的《自定义404》文章 基础上增加了一些自己的实际操作记录和修改,内容依旧属于原作者所有。转载无需和我联系,但请注明文章来源。如果侵权之处,请联系博主进行删除,谢谢。

原始作者:《海拥

环境

2025.4.14(已解决)

警告

次配置适用于Teek@1.0.2-2025.4.10版本(其它版本可自行测试)。

提示

自己开源的 《vitepress-theme-teek-one-public》网站模板。

此模板是在《Young Kbt blog》大佬开源项目《vitepress-theme-teek 》基础上修改为自己的风格而成,感谢大佬开发得主题,大佬威武。❤️❤️

1、安装依赖

sh
pnpm add -D parallax-js
sh
npm add -D parallax-js
sh
yarn add -D parallax-js
sh
bun add -D parallax-js

2、新建组件

  • docs/.vitepress/theme/components 目录下新建 NotFound.vue 文件,内容如下:
NotFound.vue文件内容:
vue
<script setup>
import { onMounted } from "vue";
import Parallax from "parallax-js";

onMounted(() => {
  const scene = document.getElementById("scene");
  if (scene) {
    new Parallax(scene);
  }
});

const goBack = () => {
  window.history.back();
};

const gohome = () => {
  //   回到首页
  window.location.href = "/";
};

const contactMe = () => {
  window.location.href = "mailto:2675263825@qq.com";
};
</script>

<template>
  <div>
    <!-- about -->
    <div class="about">
      <a
        class="bg_links social portfolio"
        href="https://haiyongcsdn.gitee.io/"
        target="_blank"
      >
        <span class="icon"></span>
      </a>
      <a
        class="bg_links social dribbble"
        href="https://dribbble.com/rafaelalucas"
        target="_blank"
      >
        <span class="icon"></span>
      </a>
      <a
        class="bg_links social linkedin"
        href="https://www.linkedin.com/in/wang-hao-666544204/"
        target="_blank"
      >
        <span class="icon"></span>
      </a>
      <a class="bg_links logo"></a>
    </div>
    <!-- end about -->

    <nav>
      <div class="menu">
        <p class="website_name">
          <a href="https://haiyongcsdn.gitee.io/">LOGO</a>
        </p>
        <div class="menu_links">
          <a
            href="https://juejin.cn/post/7474038290216779788?searchId=20250414011044ECD152E18DDFB55D0E97"
            class="link"
            >自定义404教程</a
          >
          <a
            href="https://juejin.cn/post/6955460636151119902?searchId=2025041401265634C5E8408C802D4F1CA7"
            class="link"
            >源码</a
          >
          <a
            href="https://juejin.cn/post/7150950812489875469?searchId=2025041401265634C5E8408C802D4F1CA7"
            class="link"
            >404关灯</a
          >
        </div>
        <div class="menu_icon">
          <span class="icon"></span>
        </div>
      </div>
    </nav>

    <section class="wrapper">
      <div class="container">
        <div id="scene" class="scene" data-hover-only="false">
          <div class="circle" data-depth="1.2"></div>

          <div class="one" data-depth="0.9">
            <div class="content">
              <span class="piece"></span>
              <span class="piece"></span>
              <span class="piece"></span>
            </div>
          </div>

          <div class="two" data-depth="0.60">
            <div class="content">
              <span class="piece"></span>
              <span class="piece"></span>
              <span class="piece"></span>
            </div>
          </div>

          <div class="three" data-depth="0.40">
            <div class="content">
              <span class="piece"></span>
              <span class="piece"></span>
              <span class="piece"></span>
            </div>
          </div>

          <p class="p404" data-depth="0.50">404</p>
          <p class="p404" data-depth="0.10">404</p>
        </div>

        <div class="text">
          <article>
            <p>哎呀,您访问的页面不存在</p>
            <p>可能页面地址已更改,请联系我~</p>
            <div class="button-group">
              <button @click="goBack">返回上一页</button>
              <button @click="gohome">带我回家吧</button>
              <button @click="contactMe">联系我</button>
            </div>
          </article>
        </div>
      </div>
    </section>
  </div>
</template>

<style scoped>
@import url("https://fonts.googleapis.com/css?family=Barlow+Condensed:300,400,500,600,700,800,900|Barlow:300,400,500,600,700,800,900&display=swap");

.about {
  position: fixed;
  z-index: 10;
  bottom: 10px;
  right: 80px;
  width: 40px;
  height: 40px;
  display: flex;
  justify-content: flex-end;
  align-items: flex-end;
  transition: all 0.2s ease;
}

.about .bg_links {
  width: 40px;
  height: 40px;
  border-radius: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 100%;
  backdrop-filter: blur(5px);
  position: absolute;
}

.about .logo {
  width: 40px;
  height: 40px;
  z-index: 9;
  background-image: url(https://rafaelavlucas.github.io/assets/codepen/logo_white.svg);
  background-size: 50%;
  background-repeat: no-repeat;
  background-position: 10px 7px;
  opacity: 0.9;
  transition: all 1s 0.2s ease;
  bottom: 0;
  right: 10px;
}

.about .social {
  opacity: 0;
  right: 0;
  bottom: 0;
}

.about .social .icon {
  width: 100%;
  height: 100%;
  background-size: 20px;
  background-repeat: no-repeat;
  background-position: center;
  background-color: transparent;
  display: flex;
  transition: all 0.2s ease, background-color 0.4s ease;
  opacity: 0;
  border-radius: 100%;
}

.about .social.portfolio {
  transition: all 0.8s ease;
}

.about .social.portfolio .icon {
  background-image: url(https://rafaelavlucas.github.io/assets/codepen/link.svg);
}

.about .social.dribbble {
  transition: all 0.3s ease;
}

.about .social.dribbble .icon {
  background-image: url(https://rafaelavlucas.github.io/assets/codepen/dribbble.svg);
}

.about .social.linkedin {
  transition: all 0.8s ease;
}

.about .social.linkedin .icon {
  background-image: url(https://rafaelavlucas.github.io/assets/codepen/linkedin.svg);
}

.about:hover {
  width: 105px;
  height: 105px;
  transition: all 0.6s cubic-bezier(0.64, 0.01, 0.07, 1.65);
}

.about:hover .logo {
  opacity: 1;
  transition: all 0.6s ease;
}

.about:hover .social {
  opacity: 1;
}

.about:hover .social .icon {
  opacity: 0.9;
}

.about:hover .social:hover {
  background-size: 28px;
}

.about:hover .social:hover .icon {
  background-size: 65%;
  opacity: 1;
}

.about:hover .social.portfolio {
  right: 0;
  bottom: calc(100% - 40px);
  transition: all 0.3s 0s cubic-bezier(0.64, 0.01, 0.07, 1.65);
}

.about:hover .social.portfolio .icon:hover {
  background-color: #698fb7;
}

.about:hover .social.dribbble {
  bottom: 45%;
  right: 45%;
  transition: all 0.3s 0.15s cubic-bezier(0.64, 0.01, 0.07, 1.65);
}

.about:hover .social.dribbble .icon:hover {
  background-color: #ea4c89;
}

.about:hover .social.linkedin {
  bottom: 0;
  right: calc(100% - 40px);
  transition: all 0.3s 0.25s cubic-bezier(0.64, 0.01, 0.07, 1.65);
}

.about:hover .social.linkedin .icon:hover {
  background-color: #0077b5;
}

h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
li,
button,
a,
i,
input,
body {
  margin: 0;
  padding: 0;
  list-style: none;
  border: 0;
  -webkit-tap-highlight-color: transparent;
  text-decoration: none;
  color: inherit;
}

h1:focus,
h2:focus,
h3:focus,
h4:focus,
h5:focus,
h6:focus,
p:focus,
ul:focus,
li:focus,
button:focus,
a:focus,
i:focus,
input:focus,
body:focus {
  outline: 0;
}

body {
  margin: 0;
  padding: 0;
  height: auto;
  font-family: "Barlow", sans-serif;
  background: var(--bg-color);
}

.logo {
  position: fixed;
  z-index: 5;
  bottom: 10px;
  right: 10px;
  width: 40px;
  height: 40px;
  border-radius: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background: rgba(0, 0, 0, 0.1);
  border-radius: 100%;
  backdrop-filter: blur(5px);
}

.logo img {
  width: 55%;
  height: 55%;
  transform: translateY(-1px);
  opacity: 0.8;
}

nav .menu {
  width: 100%;
  height: 80px;
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 5%;
  box-sizing: border-box;
  z-index: 3;
}

nav .menu .website_name {
  color: var(--vp-c-brand-1);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: 1px;
  background: white;
  padding: 4px 8px;
  border-radius: 2px;
  opacity: 0.5;
  transition: all 0.4s ease;
  cursor: pointer;
}

nav .menu .website_name:hover {
  opacity: 1;
}

nav .menu .menu_links {
  transition: all 0.4s ease;
  opacity: 0.5;
}

nav .menu .menu_links:hover {
  opacity: 1;
}

@media screen and (max-width: 799px) {
  nav .menu .menu_links {
    display: none;
  }
}

nav .menu .menu_links .link {
  color: var(--vp-c-brand-1);
  text-transform: uppercase;
  font-weight: 500;
  margin-right: 50px;
  letter-spacing: 2px;
  position: relative;
  transition: all 0.3s 0.2s ease;
}

nav .menu .menu_links .link:last-child {
  margin-right: 0;
}

nav .menu .menu_links .link:before {
  content: "";
  position: absolute;
  width: 0px;
  height: 4px;
  background: linear-gradient(90deg, #ffedc0 0%, #ff9d87 100%);
  bottom: -10px;
  border-radius: 4px;
  transition: all 0.4s cubic-bezier(0.82, 0.02, 0.13, 1.26);
  left: 100%;
}

nav .menu .menu_links .link:hover {
  opacity: 1;
  color: #fb8a8a;
}

nav .menu .menu_links .link:hover:before {
  width: 40px;
  left: 0;
}

nav .menu .menu_icon {
  width: 40px;
  height: 40px;
  position: relative;
  display: none;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}

@media screen and (max-width: 799px) {
  nav .menu .menu_icon {
    display: flex;
  }
}

nav .menu .menu_icon .icon {
  width: 24px;
  height: 2px;
  background: white;
  position: absolute;
}

nav .menu .menu_icon .icon:before,
nav .menu .menu_icon .icon:after {
  content: "";
  width: 100%;
  height: 100%;
  background: inherit;
  position: absolute;
  transition: all 0.3s cubic-bezier(0.49, 0.04, 0, 1.55);
}

nav .menu .menu_icon .icon:before {
  transform: translateY(-8px);
}

nav .menu .menu_icon .icon:after {
  transform: translateY(8px);
}

nav .menu .menu_icon:hover .icon {
  background: #ffedc0;
}

nav .menu .menu_icon:hover .icon:before {
  transform: translateY(-10px);
}

nav .menu .menu_icon:hover .icon:after {
  transform: translateY(10px);
}

.wrapper {
  display: grid;
  grid-template-columns: 1fr;
  justify-content: center;
  align-items: center;
  height: 100vh;
  overflow-x: hidden;
  /* background: #695681; */
}

.wrapper .container {
  margin: 0 auto;
  transition: all 0.4s ease;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.wrapper .container .scene {
  position: absolute;
  width: 100vw;
  height: 100vh;
  vertical-align: middle;
}

.wrapper .container .one,
.wrapper .container .two,
.wrapper .container .three,
.wrapper .container .circle,
.wrapper .container .p404 {
  width: 60%;
  height: 60%;
  top: 20% !important;
  left: 20% !important;
  min-width: 400px;
  min-height: 400px;
}

.wrapper .container .one .content,
.wrapper .container .two .content,
.wrapper .container .three .content,
.wrapper .container .circle .content,
.wrapper .container .p404 .content {
  width: 600px;
  height: 600px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  animation: content 0.8s cubic-bezier(1, 0.06, 0.25, 1) backwards;
}

@keyframes content {
  0% {
    width: 0;
  }
}

.wrapper .container .one .content .piece,
.wrapper .container .two .content .piece,
.wrapper .container .three .content .piece,
.wrapper .container .circle .content .piece,
.wrapper .container .p404 .content .piece {
  width: 200px;
  height: 80px;
  display: flex;
  position: absolute;
  border-radius: 80px;
  z-index: 1;
  animation: pieceLeft 8s cubic-bezier(1, 0.06, 0.25, 1) infinite both;
}

@keyframes pieceLeft {
  50% {
    left: 80%;
    width: 10%;
  }
}

@keyframes pieceRight {
  50% {
    right: 80%;
    width: 10%;
  }
}

@media screen and (max-width: 799px) {
  .wrapper .container .one,
  .wrapper .container .two,
  .wrapper .container .three,
  .wrapper .container .circle,
  .wrapper .container .p404 {
    width: 90%;
    height: 90%;
    top: 5% !important;
    left: 5% !important;
    min-width: 280px;
    min-height: 280px;
  }
}

@media screen and (max-height: 660px) {
  .wrapper .container .one,
  .wrapper .container .two,
  .wrapper .container .three,
  .wrapper .container .circle,
  .wrapper .container .p404 {
    min-width: 280px;
    min-height: 280px;
    width: 60%;
    height: 60%;
    top: 20% !important;
    left: 20% !important;
  }
}

.wrapper .container .text {
  width: 60%;
  height: 40%;
  min-width: 400px;
  min-height: 500px;
  position: absolute;
  margin: 40px 0;
  animation: text 0.6s 1.8s ease backwards;
}

@keyframes text {
  0% {
    opacity: 0;
    transform: translateY(40px);
  }
}

@media screen and (max-width: 799px) {
  .wrapper .container .text {
    min-height: 400px;
    height: 80%;
  }
}

.wrapper .container .text article {
  width: 400px;
  position: absolute;
  bottom: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
}

@media screen and (max-width: 799px) {
  .wrapper .container .text article {
    width: 100%;
  }
}

.wrapper .container .text article p {
  color: white;
  font-size: 18px;
  letter-spacing: 0.6px;
  margin-bottom: 40px;
  text-shadow: 6px 6px 10px #32243e;
}

.wrapper .container .text article button {
  height: 40px;
  padding: 0 30px;
  border-radius: 50px;
  cursor: pointer;
  box-shadow: 0px 15px 20px rgba(54, 24, 79, 0.5);
  z-index: 3;
  color: var(--vp-c-brand-1);
  background-color: white;
  text-transform: uppercase;
  font-weight: 600;
  font-size: 12px;
  transition: all 0.3s ease;
}

.wrapper .container .text article button:hover {
  box-shadow: 0px 10px 10px -10px rgba(54, 24, 79, 0.5);
  transform: translateY(5px);
  background: #fb8a8a;
  color: white;
}

.wrapper .container .p404 {
  font-size: 200px;
  font-weight: 700;
  letter-spacing: 4px;
  color: white;
  display: flex !important;
  justify-content: center;
  align-items: center;
  position: absolute;
  z-index: 2;
  animation: anime404 0.6s cubic-bezier(0.3, 0.8, 1, 1.05) both;
  animation-delay: 1.2s;
}

@media screen and (max-width: 799px) {
  .wrapper .container .p404 {
    font-size: 100px;
  }
}

@keyframes anime404 {
  0% {
    opacity: 0;
    transform: scale(10) skew(20deg, 20deg);
  }
}

.wrapper .container .p404:nth-of-type(2) {
  color: #36184f;
  z-index: 1;
  animation-delay: 1s;
  filter: blur(10px);
  opacity: 0.8;
}

.wrapper .container .circle {
  position: absolute;
}

.wrapper .container .circle:before {
  content: "";
  position: absolute;
  width: 800px;
  height: 800px;
  background-color: rgba(54, 24, 79, 0.2);
  border-radius: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: inset 5px 20px 40px rgba(54, 24, 79, 0.25), inset 5px 0px 5px rgba(50, 36, 62, 0.3),
    inset 5px 5px 20px rgba(50, 36, 62, 0.25), 2px 2px 5px rgba(255, 255, 255, 0.2);
  animation: circle 0.8s cubic-bezier(1, 0.06, 0.25, 1) backwards;
}

@keyframes circle {
  0% {
    width: 0;
    height: 0;
  }
}

@media screen and (max-width: 799px) {
  .wrapper .container .circle:before {
    width: 400px;
    height: 400px;
  }
}

.wrapper .container .one .content:before {
  content: "";
  position: absolute;
  width: 600px;
  height: 600px;
  background-color: rgba(54, 24, 79, 0.3);
  border-radius: 100%;
  box-shadow: inset 5px 20px 40px rgba(54, 24, 79, 0.25), inset 5px 0px 5px rgba(50, 36, 62, 0.3),
    inset 5px 5px 20px rgba(50, 36, 62, 0.25), 2px 2px 5px rgba(255, 255, 255, 0.2);
  animation: circle 0.8s 0.4s cubic-bezier(1, 0.06, 0.25, 1) backwards;
}

@media screen and (max-width: 799px) {
  .wrapper .container .one .content:before {
    width: 300px;
    height: 300px;
  }
}

.wrapper .container .one .content .piece {
  background: linear-gradient(90deg, #8077ea 13.7%, #eb73ff 94.65%);
}

.wrapper .container .one .content .piece:nth-child(1) {
  right: 15%;
  top: 18%;
  height: 30px;
  width: 120px;
  animation-delay: 0.5s;
  animation-name: pieceRight;
}

.wrapper .container .one .content .piece:nth-child(2) {
  left: 15%;
  top: 45%;
  width: 150px;
  height: 50px;
  animation-delay: 1s;
  animation-name: pieceLeft;
}

.wrapper .container .one .content .piece:nth-child(3) {
  left: 10%;
  top: 75%;
  height: 20px;
  width: 70px;
  animation-delay: 1.5s;
  animation-name: pieceLeft;
}

.wrapper .container .two .content .piece {
  background: linear-gradient(90deg, #ffedc0 0%, #ff9d87 100%);
}

.wrapper .container .two .content .piece:nth-child(1) {
  left: 0%;
  top: 25%;
  height: 40px;
  width: 120px;
  animation-delay: 2s;
  animation-name: pieceLeft;
}

.wrapper .container .two .content .piece:nth-child(2) {
  right: 15%;
  top: 35%;
  width: 180px;
  height: 50px;
  animation-delay: 2.5s;
  animation-name: pieceRight;
}

.wrapper .container .two .content .piece:nth-child(3) {
  right: 10%;
  top: 80%;
  height: 20px;
  width: 160px;
  animation-delay: 3s;
  animation-name: pieceRight;
}

.wrapper .container .three .content .piece {
  background: #fb8a8a;
}

.wrapper .container .three .content .piece:nth-child(1) {
  left: 25%;
  top: 35%;
  height: 20px;
  width: 80px;
  animation-name: pieceLeft;
  animation-delay: 3.5s;
}

.wrapper .container .three .content .piece:nth-child(2) {
  right: 10%;
  top: 55%;
  width: 140px;
  height: 40px;
  animation-name: pieceRight;
  animation-delay: 4s;
}

.wrapper .container .three .content .piece:nth-child(3) {
  left: 40%;
  top: 68%;
  height: 20px;
  width: 80px;
  animation-name: pieceLeft;
  animation-delay: 4.5s;
}

.button-group {
  display: flex;
  gap: 20px;
}
</style>

3、注册组件

  • docs/.vitepress/theme/index.ts中注册组件
ts
import { h } from "vue";
import DefaultTheme from "vitepress/theme";
import NotFound from "./components/NotFound.vue"; // 导入404组件

export default {
  // 自定义布局配置
  Layout: () => {
    const props = {};
    // 获取 frontmatter
    const { frontmatter } = useData();

    // 添加自定义 class
    if (frontmatter.value?.layoutClass) {
      props.class = frontmatter.value.layoutClass;
    }
    return h(DefaultTheme.Layout, props, {
      // 自定义文档底部
      "doc-after": () => h(siteFooter),
      // 自定义404页面内容
      "not-found": () => h(NotFound), 
    });
  },
};
自己实际docs/.vitepress/theme/index.ts配置内容:
ts
import Teek, { teekConfigSymbol } from "vitepress-theme-teek";
import TeekLayoutProvider from "./components/TeekLayoutProvider.vue";
import "vitepress-theme-teek/index.css";
import NoticeContent from "./components/NoticeContent.vue";
import BannerImgArrow from "./components/BannerImgArrow.vue";

import { defineComponent, h, nextTick, provide, watch } from "vue";
import { useData, useRoute } from "vitepress";
import  { artalkSymbol, giscusSymbol, walineSymbol } from "vitepress-theme-teek";

import "vitepress-theme-teek/vp-plus/code-block-mobile.scss"; // 移动端代码块样式加 padding
import "vitepress-theme-teek/vp-plus/sidebar.scss"; // 侧边栏字体样式
import "vitepress-theme-teek/vp-plus/nav.scss"; // 导航栏样式
import "vitepress-theme-teek/vp-plus/nav-blur.scss"; // 导航栏毛玻璃样式
import "vitepress-theme-teek/vp-plus/aside.scss"; // 文章目录样式
import "vitepress-theme-teek/vp-plus/doc-h1-gradient.scss"; // 文档以及标题样式
import "vitepress-theme-teek/vp-plus/mark.scss"; // 文章 mark 标签样式
import "vitepress-theme-teek/vp-plus/container.scss"; // Markdown 容器样式
import "vitepress-theme-teek/vp-plus/container-left.scss"; // Markdown 容器左框样式
// import "vitepress-theme-teek/vp-plus/container-flow.scss"; // Markdown 容器流体样式
import "vitepress-theme-teek/vp-plus/blockquote.scss"; // 引用样式
// import "vitepress-theme-teek/vp-plus/blockquote-one.scss"; // 引用样式-增强
import "vitepress-theme-teek/vp-plus/index-rainbow.scss"; // Vitepress 首页彩虹渐变样式
import "vitepress-theme-teek/tk-plus/banner-desc-gradient.scss"; // Banner 描述渐变样式
import "vitepress-theme-teek/tk-plus/banner-full-img-scale.scss"; // Banner 全屏图片放大样式


import "./styles/code-bg.scss";
import "./styles/index.scss";


import { useFooterRuntime } from "./helper/useFooterRuntime"; // 首页底部添加运行时间
import confetti from "./components/Confetti.vue"; //导入五彩纸屑组件
import "vitepress-markdown-timeline/dist/theme/index.css"; // 引入时间线样式
import "virtual:group-icons.css"; //代码组图标样式
import NotFound from "./components/NotFound.vue"; // 导入404组件



// 评论组件
import { init } from "@waline/client";
import "@waline/client/style";
import Giscus from "@giscus/vue";
import "artalk/Artalk.css";
import Artalk from "artalk";


export default {
  extends: Teek,
  enhanceApp({ app }) {
    // 注册组件
    app.component("confetti", confetti); //五彩纸屑
  },
  Layout: defineComponent({
    name: "LayoutProvider",
    setup() {
      const { frontmatter, isDark, page } = useData();
      const { start, stop } = useFooterRuntime();
      const route = useRoute();

      // 注入评论区实例
      provide(walineSymbol, (options, el) => init({ serverURL: options.serverURL!, dark: options.dark, el }));
      provide(giscusSymbol, () => Giscus);
      provide(artalkSymbol, (options, el) =>
        Artalk.init({
          el,
          darkMode: isDark.value,
          pageKey: route.path,
          pageTitle: page.value.title,
          server: options.server,
          site: options.site,
        })
      );

      watch(
        frontmatter,
        () => {
          nextTick(() => {
            if (frontmatter.value.layout === "home") start();
            else stop();
          });
        },
        { immediate: true }
      );

      return () =>
        h(TeekLayoutProvider, null, {
          "teek-notice-content": () => h(NoticeContent),
          "teek-home-banner-feature-after": () => h(BannerImgArrow),
          // 自定义404页面内容
          "not-found": () => h(NotFound), 
          // "teek-home-before": () => h("div", null, "teek-home-before"),
          // "teek-home-after": () => h("div", null, "teek-home-after"),
          // "teek-home-banner-before": () => h("div", null, "teek-home-banner-before"),
          // "teek-home-banner-after": () => h("div", null, "teek-home-banner-after"),
          // "teek-home-banner-content-before": () => h("div", null, "teek-home-banner-content-before"),
          // "teek-home-banner-content-after": () => h("div", null, "teek-home-banner-content-after"),
          // "teek-home-banner-feature-after": () => h("div", null, "teek-home-banner-feature-after"),
          // "teek-home-post-before": () => h("div", null, "teek-home-post-before"),
          // "teek-home-post-after": () => h("div", null, "teek-home-post-after"),
          // "teek-home-info-before": () => h("div", null, "teek-home-info-before"),
          // "teek-home-info-after": () => h("div", null, "teek-home-info-after"),
          // "teek-home-my-before": () => h("div", null, "teek-home-my-before"),
          // "teek-home-my-after": () => h("div", null, "teek-home-my-after"),
          // "teek-home-top-article-before": () => h("div", null, "teek-home-top-article-before"),
          // "teek-home-top-article-after": () => h("div", null, "teek-home-top-article-after"),
          // "teek-home-category-before": () => h("div", null, "teek-home-category-before"),
          // "teek-home-category-after": () => h("div", null, "teek-home-category-after"),
          // "teek-home-tag-before": () => h("div", null, "teek-home-tag-before"),
          // "teek-home-tag-after": () => h("div", null, "teek-home-tag-after"),
          // "teek-home-friend-link-before": () => h("div", null, "teek-home-friend-link-before"),
          // "teek-home-friend-link-after": () => h("div", null, "teek-home-friend-link-after"),
          // "teek-home-doc-analysis-before": () => h("div", null, "teek-home-doc-analysis-before"),
          // "teek-home-doc-analysis-after": () => h("div", null, "teek-home-doc-analysis-after"),
          // "teek-footer-before": () => h("div", null, "teek-footer-before"),
          // "teek-footer-after": () => h("div", null, "teek-footer-after"),

          // "teek-article-analyze-before": () => h("div", null, "teek-article-analyze-before"),
          // "teek-article-analyze-after": () => h("div", null, "teek-article-analyze-after"),
          // "teek-comment-before": () => h("div", null, "teek-comment-before"),
          // "teek-comment-after": () => h("div", null, "teek-comment-after"),
          // "teek-page-top-before": () => h("div", null, "teek-page-top-before"),
          // "teek-page-top-after": () => h("div", null, "teek-page-top-after"),

          // "teek-archives-top-before": () => h("div", null, "teek-archives-top-before"),
          // "teek-archives-top-after": () => h("div", null, "teek-archives-top-after"),
          // "teek-catalogue-top-before": () => h("div", null, "teek-catalogue-top-before"),
          // "teek-catalogue-top-after": () => h("div", null, "teek-catalogue-top-after"),

          // "teek-right-bottom-before": () => h("div", null, "teek-right-bottom-before"),
          // "teek-right-bottom-after": () => h("div", null, "teek-right-bottom-after"),
        });
    },
  }),


};

image-20250414184006335

image-20250414184027537

4、测试

运行项目,随便输入一个不存在的url:

https://onedayxyy.cn/xx

image-20250414205614525

测试结束。

扩展

原作者文档

https://juejin.cn/post/7474038290216779788?searchId=20250414011044ECD152E18DDFB55D0E97

在自定义的theme/index.js文件中去配置就行。

javascript
import { h } from "vue";
import DefaultTheme from "vitepress/theme";
import NotFound from "./components/404.vue";

export default {
  // 自定义布局配置
  Layout: () => {
    const props = {};
    // 获取 frontmatter
    const { frontmatter } = useData();

    // 添加自定义 class
    if (frontmatter.value?.layoutClass) {
      props.class = frontmatter.value.layoutClass;
    }
    return h(DefaultTheme.Layout, props, {
      // 自定义文档底部
      "doc-after": () => h(siteFooter),
      // 自定义404页面内容
      "not-found": () => h(NotFound),
    });
  },
};

404.vue 页面

xml
<template>
  <div class="not-found">
    <h1>404</h1>
    <p>哎呀,您访问的页面不存在!</p>
    <a href="/404.html" target="_self">返回首页</a>
  </div>
</template>

这样就可以自定义VitePress的404页面内容了。

其它404效果

https://juejin.cn/post/6955460636151119902?searchId=2025041401265634C5E8408C802D4F1CA7

image-20250414204633413

源码位置:

image-20250414204922636

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 个人网站

image-20250109220325748

🍀 微信二维码

x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号

《云原生架构师实战》

image-20230107215126971

🍀 csdn

https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎

https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

如果你还有疑惑,可以去我的网站查看更多内容或者联系我帮忙查看。

如果你有更好的方式,评论区留言告诉我。谢谢!

好了,本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

最近更新