接上一節:從零用VitePress搭建博客教程(4) – 如何自定義首頁佈局和主題樣式修改? 上一節其實我們也簡單說了自定義頁面模板,這一節更加詳細一點說明,開始之前我們要知道在vitePress中,.md的文件是可以直接編寫vue的代碼的。 比如我們現在來自定義一個前端網址導航頁面 八、自定義一些 ...
接上一節:從零用VitePress搭建博客教程(4) – 如何自定義首頁佈局和主題樣式修改?
上一節其實我們也簡單說了自定義頁面模板,這一節更加詳細一點說明,開始之前我們要知道在vitePress中,.md的文件是可以直接編寫vue的代碼的。
比如我們現在來自定義一個前端網址導航頁面
八、自定義一些頁面模板
想自定義頁面模板樣式,該如何做呢?
我們先在theme/components下新建siteList.vue文件,編寫模板,代碼如下:
<template> <!-- 網址分類模塊 --> <section class="site-section"> <!-- 標題 --> <h2 class="title">{{ props.title }}</h2> <!-- 網址列表 --> <ul class="list"> <li class="item" v-for="(v, index) in props.data" :key="v.name"> <a class="link" :href="v.link" target="_blank"> <span class="num">{{ index + 1 }}</span> <h4 class="name">{{ v.name }}</h4> <p class="desc">{{ v.desc }}</p> </a> </li> </ul> </section> </template> <script setup> const props = defineProps({ title: String, data: { type: Array, default: [], }, }); </script> <style lang="scss" scoped> /*單行文本省略號*/ @mixin single-ellipsis { overflow: hidden; word-wrap: normal; white-space: nowrap; text-overflow: ellipsis; } .site-section { .title { color: #222; } .list { display: flex; flex-wrap: wrap; list-style: none; padding-left: 0; .item { width: 212px; margin: 15px 15px 0 0px; background: #fff; position: relative; .link { width: 210px; display: block; border: 1px solid #e3e3e3; padding-bottom: 8px; border-radius: 6px; .num { display: block; width: 24px; height: 18px; line-height: 18px; position: absolute; color: #666; font-size: 14px; text-align: center; right: 5px; top: 5px; } .name { width: 80%; height: 26px; padding-left: 10px; font-size: 16px; font-weight: 600; color: #06a4fa; margin-top: 15px; @include single-ellipsis; } .desc { font-size: 12px; margin: 10px 10px 0; color: #b1b1b1; height: 36px; line-height: 18px; @include single-ellipsis; } &:hover { text-decoration: none; border: 1px solid var(--vp-c-brand); filter: brightness(1.15); box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1); transform: rotateY(-0.1deg) scale(1.001) translateZ(0); transition: all 0.24s ease; .name { color: var(--vp-c-brand); } .num { background: var(--vp-c-brand); color: #fff; } } } } } } </style>
上面我們寫好組件代碼後,需註冊為全局組件,如下theme/index.js的配置,把SiteList註冊為全局組件,然後在頁面引用即可。
// https://vitepress.dev/guide/custom-theme import { h } from "vue"; import siteList from "./components/siteList.vue"; import DefaultTheme from "vitepress/theme"; import "./styles/custom.scss"; import "./styles/site.scss"; import "./styles/rainbow.css"; export default { ...DefaultTheme, NotFound: () => "404", // <- this is a Vue 3 functional component enhanceApp({ app, router, siteData }) { // app is the Vue 3 app instance from createApp() // router is VitePress' custom router (see `lib/app/router.js`) // siteData is a ref of current site-level metadata. app.component("SiteList", siteList); }, };
--- pageClass: site-layout ---
然後在下麵寫樣式即可
.site-layout { ... }
當然還有一種方法是:我們還可以在theme/index.js,通過js添加(Layout配置),這個一個頁面可以添加多個className了。
// https://vitepress.dev/guide/custom-theme import { useData } from "vitepress"; import siteList from "./components/siteList.vue"; import DefaultTheme from "vitepress/theme"; import "./styles/custom.scss"; import "./styles/site.scss"; import "./styles/rainbow.css"; export default { ...DefaultTheme, NotFound: () => "404", // <- this is a Vue 3 functional component enhanceApp({ app, router, siteData }) { // app is the Vue 3 app instance from createApp() // router is VitePress' custom router (see `lib/app/router.js`) // siteData is a ref of current site-level metadata. // 註冊全局組件 app.component("SiteList", siteList); }, // 自定義佈局配置 Layout: () => { const props = {}; // 獲取 frontmatter const { frontmatter } = useData(); /* 添加自定義 class */ if (frontmatter.value?.layoutClass) { props.class = frontmatter.value.layoutClass; } }, };
然後同樣的page.md頁面,我們可以通過layoutClass設置另一個className了,如下
--- layoutClass: site-page pageClass: site-layout ---
同樣還是上面的page.md,我們使用組件如下
--- pageClass: site-layout --- <SiteList v-for="model in siteData" :key="model.title" :title="model.title" :data="model.items" /> <script setup> // 網址導航頁面的數據 import siteData from "./data/page.js"; </script>
效果
從上面圖中可以看出,我們發現右邊沒有側邊導航,那麼如何使頁面標題變成側邊目錄呢?
這個時候需要用到
<template> <!-- 網址分類模塊 --> <!-- <backTop></backTop> --> <section class="site-section"> <!-- 瞄點標題 --> <h2 class="title" :id="createTitle"> {{ props.title }} <a class="anchor" :href="`#${createTitle}`" aria-hidden="true"></a> </h2> <!-- 網址列表 --> <ul class="list"> <li class="item" v-for="(v, index) in props.data" :key="v.name"> <a class="link" :href="v.link" target="_blank"> <span class="num">{{ index + 1 }}</span> <h4 class="name">{{ v.name }}</h4> <p class="desc">{{ v.desc }}</p> </a> </li> </ul> </section> </template> <script setup> import { computed } from "vue"; import { slugify } from "@mdit-vue/shared"; const props = defineProps({ title: String, data: { type: Array, default: [], }, }); // 生成側邊欄markdown的目錄 const createTitle = computed(() => { return slugify(props.title); }); </script>
發現目錄已經有了,效果如下:
這個時候目錄是在頁面右邊的,那麼如何變成在左側邊欄呢?我們通過樣式調整即可,site.scss
/** 網址導航頁面樣式 **/ .site-layout { /*佈局調整*/ .VPDoc { .container { max-width: 100% !important; justify-content: flex-start !important; .aside { order: 1; } .content { order: 2; max-width: 100% !important; .content-container { max-width: 100% !important; } } .main { height: auto; overflow: hidden; .vp-doc h2 { margin: 0; } } } } /* 隱藏底部的在 github 上編輯此頁模塊*/ .VPDocFooter { display: none; } }
我們新建一個siteFooter.vue組件,然後在theme/index.js通過h函數配置即可,這裡使用到doc-after插槽,
預設主題佈局中可用插槽的完整列表:
<template> <div class="site-footer"> 網址導航自定義底部信息 </div> </template>
mport { h } from "vue"; import siteFooter from "./components/siteFooter.vue"; import DefaultTheme from "vitepress/theme"; export default { ...DefaultTheme, NotFound: () => "404", // <- this is a Vue 3 functional component enhanceApp({ app, router, siteData }) { // app is the Vue 3 app instance from createApp() // router is VitePress' custom router (see `lib/app/router.js`) // siteData is a ref of current site-level metadata. // 註冊全局組件 }, // 自定義佈局配置 Layout: () => { return h(DefaultTheme.Layout, props, { // 自定義文檔底部,使用doc-after插槽 "doc-after": () => h(siteFooter), }); }, };