iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
Vue.js

用 Nuxt Content 搭配 Obsidian 建立自己的 Digital Garden系列 第 27

為每一頁分頁標題都加上網站名稱

  • 分享至 

  • xImage
  •  

目前網站在瀏覽器的分頁名稱上,要嘛直接顯示路徑,要嘛就是只顯示文章的標題。對網站的識別性來說,這兩者的體驗都是不好的,今天就來實作讓普通頁面預設是網站名稱,如果是文章,則是後綴網站名稱,讓分頁更具識別性。

機制

在實作時,要先了解一個 Nuxt Content 關於 title 的機制,這部分是我自己測試出來的,實際行為請以 Nuxt Content 的 source code 為主:

  1. 當有設置 app.head.title 時,第一次進入網站頁面會以該值為 <Title />
  2. 在有使用 <ContentDoc /> 的頁面中,若對應的內容檔案在 Frontmatter 有設定 title 時,會更新當前 <Title /> 為 title。
  3. 在有使用 <ContentDoc /> 的頁面中,若對應的內容檔案在 Frontmatter 沒有設定 title 時,系統會用檔案名稱作為 <Title />,且已經會將每字首位字母大寫、並將連字號轉成空白的。
  4. 在沒有使用 <ContentDoc /> ,不會更新 <Title />,就算 <Title /> 已被改成其他內容檔案的名稱,也不會改回 app.head.title 的值。
  5. 內容檔案名稱是 index.md 若對應的內容檔案在 Frontmatter 沒有設定 title 時,不會更新 <Title />

若要用虛擬程式碼去解釋這個規則,大概是長得像這樣:

const main = () => {
  config = useConfig()
  head = useHead()
  head.title = config.title

  changePageHooks.add((page) => {
    if (!page.contains('<ContentDoc />')) {
      return
    }

    if (!page.content.filename === 'index.md') {
      return
    }
  
    if (page.content.frontmatter.title) {
      head.title = page.contentfrontmatter.title
    } else {
      head.title = page.content.filename.toTitleCase()
    }
  })   
}

所以就會發生一個情況是,當我切換到某篇文章頁面,分頁標題更新後,如果到了其他不會更新分頁標題的頁面,就會變得牛頭不對馬尾的情況。

為了應對這個狀況,我新增了一個 useGarden() 的 composable 來處理這個狀態,只要頁面或主要元件有使用就能顯示我期望的標題。

實作

新增 @/composables/useGarden.ts

import { Post } from "@/types"
import { startCase } from "@/libraries/formater"

function getTitleByRouteSlug() {
  const route = useRoute()
  const slug = route.name?.toString() || ''
  return startCase(slug)
}

export function useGarden(post : Post|undefined = undefined  ) {
  const title = post?.title || getTitleByRouteSlug() || ''
  const separator = title ? ' - ' : ''

  const headTitle = computed(() => `${title}${separator}My Digital Garden`)

  if (post) {
    post.head = post.head || {}
    post.head.title = post.head.title || headTitle
  }

  useHead({title: headTitle})
}

這個 composable 會先決定標題,若有文章且有 title 屬性,則直接沿用;若無則使用其 slug 去轉換。最後在這個標題後面加上網站名稱。

接著我在 @/index.vue@/components/List/Page.vue@/components/Post/Page.vue@/pages/tag/index.vue@/pages/tag/index.vue 加上 useGarden() 就可以覆蓋多數情況了。


上一篇
Icon:增加圖示讓視覺更多元
下一篇
為 Digital Garden 新增留言功能
系列文
用 Nuxt Content 搭配 Obsidian 建立自己的 Digital Garden30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言