---
# System prepended metadata

title: "\U0001F3C5 Day 13 - SEO Meta Components"
tags: [2024 Nuxt 直播班]

---

# 🏅 Day 13 - SEO Meta Components 
## 今日學習目標

- 學習如何使用 Nuxt3 的 SEO 元件來設定靜態與動態的頁面 Meta 資訊
- 理解如何傳入具響應性的資料來動態更新 SEO Meta 資訊

## 前言

在 Day 11 和 Day12 ，我們學習了四種設定頁面 SEO 的方法，包括全域設定 ( 在  `nuxt.config.ts` 中的`app.head` 預設設定 ) ，以及使用 `useHead()`、`useSeoMeta()`、`useServerSeoMeta()` Composable 來設定單一頁面的 SEO。接下將介紹如何透過 Nuxt3 的內建 SEO 元件，在頁面模板加入靜態和動態變化的 SEO。


## SEO Meta Components

Nuxt3 提供了內建的 SEO 元件，讓我們可以直接在模板中設定 SEO 資訊。以下是這些元件的名稱以及其對應的功能 : 

- **`<Title>`**：設定 `<title></title>` 標籤，在瀏覽器標籤上顯示頁面標題 。

```
ex: 
<Title>網站標題</Title>
```

- **`<Meta>`**：設定 `<meta />`標籤，例如 `description`、`keywords`。

```
ex:
<Meta name="description" content="網頁的描述"/>
<Meta name="keywords" content="關鍵詞1, 關鍵詞2"/>
```

- **`<Base>`**：設定 `<base />` 標籤，指定所有連結的基準 URL。

```
ex:
<Base href="https://example.com/"/>
```

- **`<NoScript>`**：設定 `<noscript></noscript>` 標籤，提供給不支援 JavaScript  瀏覽器的提示訊息。

```
ex;
<NoScript>此網頁需要支援 JavaScript 才能正確運行，請先至你的瀏覽器設定中開啟 JavaScript。</NoScript>
```

- **`<Style>`**：設定`<style></style>`標籤，在 `style` 元素內設定 CSS 。可以有兩種寫法 :

```
ex:
// 寫法一. 樣式寫在標籤內
<Style  type="text/css">
  body {
    background-color: #f0f0f0;
  }
</Style>

// 寫法二. 樣式寫在標籤的 children 屬性
 <Style type="text/css" children="body { background-color: #f0f0f0; }"></Style>
```

- **`<Link>`**：設定 `<link />` 標籤，例如引入外部 CSS。

```
ex: 引入 animate.css
<Link rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
```

- **`<Html>`**：設定 `<html></html>` 標籤的屬性，例如 `lang`。在使用上會包在 `<Head>` 和`<Body>`的外層。如果沒有特別要設定屬性的話可以省略這一層 `<Html>` 元件。

```
ex:
<Html lang="en">
 <Head></Head>
 <Body></Body>
</Html>
```

- **`<Body>`**：設定 `<body></body>` 標籤的屬性，例如 `class` 或 `id`。在使用上會包在 `<Html>` 的內層。如果沒有特別要設定屬性的話可以省略這一層 `<Body>`元件。

```
ex:
<Html>
  <Head></Head>
  <Body class="body" id="body"></Body>
</Html>
```

- **`<Head>`**：設定 `<head></head>` 標籤的內容 。在使用上會包在 `<Html>` 的內層，meta 資訊的外層。`<Html>` 如果沒有特別要設定屬性的話可以省略。

```
ex:
<Html>
    <Head>
      <Title>網站標題</Title>
      <Meta name="description" content="網頁的描述。"/>
      <Meta name="keywords" content="關鍵詞1, 關鍵詞2"/>
      <!-- 其他元件 -->
    </Head>
</Html>
```

### 使用方式

使用 SEO 元件有以下四個要點：

1. 為了避免與原生 HTML 標籤名稱重複，SEO 元件的名稱應以大寫字母開頭。例如，使用 `<Meta />` 而不是 `<meta />`。
2. 元件放入屬性名稱與屬性值的用法和原生  HTML 相同。例如原生 HTML 撰寫的 `<meta name="keywords" content="關鍵詞1, 關鍵詞2"/>`   轉換成元件的做法可以寫成 `<Meta name="keywords" content="關鍵詞1, 關鍵詞2"/>` 。
3. 撰寫 SEO 元件時建議依照與原生 HTML 的相同的結構，將頁面的 SEO 資訊包在   `<Head> </Head>`  元件內。
4. SEO 元件在伺服器端和客戶端渲染時所生成的 SEO 資訊是相同的。如果需要針對伺服器端的 SEO 設定資訊，可以使用 `useServerSeoMeta()`。

以下方範例為例，整合在模板會呈現與原生 HTML 相似的結構。 

```html
<!-- /pages/index.vue -->
<template>
  <Html lang="en">
    <Head>
      <Title>網站標題</Title>
      <Meta name="description" content="網頁的描述" />
      <Meta name="keywords" content="關鍵詞1, 關鍵詞2" />
      <NoScript
        >此網頁需要支援 JavaScript 才能正確運行，請先至你的瀏覽器設定中開啟
        JavaScript。</NoScript
      >
      <Style type="text/css"> body { background-color: #f0f0f0; } </Style>
      <Link
        rel="stylesheet"
        href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
      />
    </Head>
    <Body class="body" id="body">
      <h1>index 頁面</h1>
    </Body>
  </Html>
</template>
```

Nuxt 在解析後會將`<Html>`  與  `<Body>`  元件的屬性設定移動至 `<html>` 與 `<body>` 標籤，`<Head>`元件內的 SEO 資訊移動到 `<head></head >`。而 `<Body>` 元件內放的內容不會被移動，會被渲染在 body 標籤內 ，如下圖 : 

![day13-usage](https://hackmd.io/_uploads/B10i85FzJl.jpg)



如果沒有特別要設定屬性的話，可以省略 `<Html>` 和 `<Body>` 的嵌套。頁面的內容可以選擇不包在 `<Body>` 元件裡面。如果只有設定 SEO 資訊的需求，可以只保留 `<Head></Head>` 元件。

```html

<!-- /pages/index.vue -->
<template>
  <Head>
    <Title>網站標題</Title>
    <Meta name="description" content="網頁的描述" />
    <Meta name="keywords" content="關鍵詞1, 關鍵詞2" />
    <NoScript
      >此網頁需要支援 JavaScript 才能正確運行，請先至你的瀏覽器設定中開啟
      JavaScript。</NoScript
    >
    <Style type="text/css"> body { background-color: #f0f0f0; } </Style>
    <Link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
    />
  </Head>
  <h1>index 頁面</h1>
</template>
```


## 傳入具響應性的資料

Nuxt3 的 SEO 元件除了可以接受靜態資料，也可以接受響應性資料。也就是說，可以使用 Vue 的 `ref` 或 `computed` 來設定這些元件的屬性，讓 SEO Meta 資訊能夠根據資料變化即時更新。

### 使用 ref 設定 SEO Meta 資訊

可以使用 ref 定義具有響應性的資料，將其透過 `{{ }}` 模板語法渲染或是通過 v-bind 綁定至元件的屬性。以下範例使用了 `ref` 設定頁面標題並以 `{{title}}` 渲染，同時將網頁描述綁定至 `<Meta>` 元件的 `content` 屬性。

```html
<!-- /pages/about.vue -->
<script setup>
const title = ref("網站標題");
const description = ref("網頁的描述");
</script>

<template>
  <Head>
    <Title>{{ title }}</Title>
    <Meta name="description" :content="description" /> <!-- 使用 v-bind -->
    <Meta name="keywords" content="關鍵詞1, 關鍵詞2" />
    <NoScript
      >此網頁需要支援 JavaScript 才能正確運行，請先至你的瀏覽器設定中開啟
      JavaScript。</NoScript
    >
    <Style type="text/css"> body { background-color: #f0f0f0; } </Style>
    <Link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
    />
  </Head>

  <h1>about 頁面</h1>
</template>
```

### 使用 Computed 設定 SEO Meta 資訊

當 SEO Meta 需要透過變數或是邏輯運算來計算具有響應性的值，可以使用 Vue `computed` 處理複雜的邏輯運算，維持模板的整潔與邏輯的維護性。

以下範例使用了  `computed`  計算 socialMediaTitle 作為 og:title 和 twitter:title  共同的 content 屬性值，避免在模板中重複寫多次相同的邏輯。

```html
<script setup>
const title = ref("網站標題");
const description = ref("網頁的描述");
const socialMediaTitle = computed(() => `${title.value} | 關於我們 `);
</script>

<template>
  <Head>
    <Title>{{ title }}</Title>
    <Meta name="description" :content="description" />
    <Meta name="keywords" content="關鍵詞1, 關鍵詞2" />
    <Meta property="og:title" :content="socialMediaTitle" />
    <Meta name="twitter:title" :content="socialMediaTitle" />
    <NoScript
      >此網頁需要支援 JavaScript 才能正確運行，請先至你的瀏覽器設定中開啟
      JavaScript。</NoScript
    >
    <Style type="text/css"> body { background-color: #f0f0f0; } </Style>
    <Link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
    />
  </Head>

  <h1>about 頁面</h1>
</template>
```

<br>

> 今日學習的[範例 Code - 資料夾: day13-metacomponent-seo-example](https://github.com/hexschool/nuxt-daily-tasks-2024) 

## 題目
請 fork 這一份 [模板](https://github.com/jasonlu0525/nuxt3-live-question/tree/day13-metacomponent-seo) 在 `/pages/room/[id].vue` 房型詳細頁面作答，完成以下條件 :

- **改寫 SEO Meta 設定**：
    - 將原本使用的 `useSeoMeta({ })` 方法，改為使用 Nuxt3 的 SEO 元件來渲染頁面的 Meta 標籤（如 `<Title>`、`<Meta>` 等）。
    - 使用 `computed` 計算出所需的 SEO Meta 資訊，避免重複邏輯，並將這些資料應用到 SEO 元件中。
    
    ```
    /*
    請將 useSeoMeta({ }) 改成 Nuxt3 SEO 元件的寫法
    重複邏輯的地方可以使用 computed 
    */
    useSeoMeta({
      title: roomObject.value.name,
      titleTemplate: (title) => `Freyja | ${title}`,
      description: () => `${roomObject.value.description}`,
      ogTitle: () => `Freyja | ${roomObject.value.name}`,
      ogDescription: () => `${roomObject.value.description}`,
      ogImage: () => `${roomObject.value.imageUrl}`,
      ogUrl: () => `https://freyja.travel.com.tw/room/${roomObject.value._id}`,
      twitterCard: "summary_large_image",
      twitterTitle: () => `Freyja | ${roomObject.value.name}`,
      twitterDescription: () => `${roomObject.value.description}`,
      twitterImage: () => `${roomObject.value.imageUrl}`,
    });
    ```

## 回報流程

將答案上傳至 GitHub 並複製 GitHub  repo 連結貼至底下回報就算完成了喔 !
解答位置請參考下圖（需打開程式碼的部分觀看）

![](https://i.imgur.com/vftL5i0.png)

<!--   

解答 : https://github.com/jasonlu0525/nuxt3-live-answer/tree/day13-metacomponent-seo

-->




回報區
---
| #   | Discord | Github / 答案 |
| --- | ----- | ----- |
|1|kevinhes|[Github](https://github.com/kevinhes/nuxt-daily-mission/tree/day13)|
| 2 | Steven |[Github](https://github.com/y7516552/nuxt3-live-question/tree/day13)|
| 3 | dargon | [Github](https://github.com/peterlife0617/2024-nuxt-training-homework01/tree/feature/day13) |
| 4 | MY | [Github](https://github.com/ahmomoz/nuxt3-live-question/tree/day13-metacomponent-seo-hw) |
| 5 | 眼睛 | [Github](https://github.com/Thrizzacode/nuxt3-live-question/tree/day13-metacomponent-seo) |
| 6 | LinaChen | [Github](https://github.com/Lina-SHU/nuxt3-live-question)|
| 7 | JimLin | [Github](https://github.com/junhoulin/Nuxt3-hw-day-after10/tree/day13) |
| 8 | wei_Rio | [Github](https://github.com/wei-1539/nuxtDaily10/tree/Day-13---SEO-Meta-Components) |
| 9 | runweiting | [CodePen](https://codepen.io/weiting14/pen/yLmmEov) |
| 10 | Rocky | [Github](https://github.com/WuRocky/Nuxt-Day13-SEO-Meta-Components.git) |
| 11 | hsin yu | [Github](https://github.com/dogwantfly/nuxt3-daily-task-live-question/tree/day13-metacomponent-seo) |
| 12 | Tough life | [Github](https://github.com/hakuei0115/Nuxt_testing) |
| 13 | 阿塔 | [Github](https://github.com/QuantumParrot/2024-Hexschool-Nuxt-Camp-Daily-Task/commit/c7aaef6c120c29a1f6a20adf9f28f31b8df54149) |
| 14 | tanuki狸 | [Github](https://github.com/tanukili/Nuxt-2024-week01-2/tree/day13-metacomponent-seo) |
| 15 | Fabio20 | [Github](https://github.com/fabio7621/nuxt3-live-question-d2/tree/nuxt-live-day13) |
| 16 | Ariel | [Github](https://github.com/Ariel0508/nuxtday9/tree/nuxtDay13) |
| 17 | lidelin | [Github](https://github.com/Lide/nuxt3-live-question/tree/day13-metacomponent-seo) |
| 18 | Johnson | [Github](https://github.com/tttom3669/2024_hex_nuxt_daily/tree/day13-metacomponent-seo) |
<!-- 
快速複製

| --- | --- | [Github]() |

-->