iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
Vue.js

Nuxt 3 初學者指南:30天從基礎到實踐系列 第 9

Day 9 – Nuxt 3 Components <ClientOnly>

  • 分享至 

  • xImage
  •  

Day 9 – Nuxt 3 Components <ClientOnly>

Nuxt 3 提供了一個名為 <ClientOnly> 的元件,用於明確控制為客戶端渲染行為,確保此元件內的元素或內容僅在客戶端呈現,這有助於提升性能並增強使用者體驗。

使用與比較

// app.vue
<template>
  <Sidebar />
  <ClientOnly>
    <Comments />
  </ClientOnly>
</template>

沒有 <ClientOnly>:SSR + CSR

// components/Sidebar.vue
<template>
  <div>
    <h1>Sidebar is both SSR and CSR</h1>
  </div>
</template>
<script setup lang="ts">
// console.log('<Sidebar>', window)
</script>

<ClientOnly> 內:只有 CSR

// components/Comments.vue
<template>
  <div>
    <h1>Comments is CSR</h1>
  </div>
</template>
<script setup lang="ts">
// console.log('<Comments>', window)
</script>

我們分別插入 <Sidebar><Comments>,並將 <Comments> 包在 <ClientOnly> 內。

渲染畫面

https://ithelp.ithome.com.tw/upload/images/20230923/20162805OffgiwODax.png

檢視網頁原始碼差異

存在 <Sidebar /> 的內容 "Sidebar is both SSR and CSR"

https://ithelp.ithome.com.tw/upload/images/20230923/20162805CpzNIxTaFY.png

不存在 <ClientOnly> 的內容 "Comments is CSR"

https://ithelp.ithome.com.tw/upload/images/20230923/20162805jJJ86l25fQ.png

window 物件差異

上方 Comments.vueSidebar.vueconsole.log(window) 註解打開。

Comments.vueconsole.log(window) 可使用

Sidebar.vueconsole.log(window) 不可使用,會直接報錯。

window 物件僅在瀏覽器中存在,但可透過 Vue 的 Lifecycle Hooks 指定呼叫的時間,如 onMounted() 呼叫 windows,因此 window 只在客戶端被呼叫。

<template>
  <div>
    <h1>Sidebar is both SSR and CSR</h1>
  </div>
</template>
<script setup lang="ts">
onMounted(()=>{
  console.log('<Sidebar>', window)
})
</script>

https://ithelp.ithome.com.tw/upload/images/20230923/20162805ThFJvWv9Qy.png

預設內容

<ClientOnly> 提供了預設的 slot,當 <ClientOnly> 元件還沒在客戶端掛載時,如果希望顯示一些預設的內容避免空白頁面可以使用 fallbackTag + fallback<template #fallback> ... </template> 來實現:

  1. fallbackTag + fallback

    // app.vue
    <template>
      <Sidebar />
      <ClientOnly fallbackTag="div" fallback="Loading ...">
        <Comments />
      </ClientOnly>
    </template>
    

    fallbackTag="div" 的作用為 <ClientOnly> 的子組件 <Comments /> 尚未在客戶端渲染完成之前,在伺服器端渲染一個 <div>Loading ...</div> 元素作為替代;若沒有指定 fallbackTag 則只會渲染一個空的 <span>

  2. <template #fallback> ... </template>

    // app.vue
    <template>
      <Sidebar />
      <ClientOnly>
        <Comments />
        <template #fallback>
          <h1>加速等待 ... </h1>
          <img src="https://attach.setn.com/newsimages/2019/09/20/2140660-PH.jpg" />
        </template>
      </ClientOnly>
    </template>
    

    加在客戶端渲染前的預設畫面,效果如同方法一;但使用 slot 的方式則可以插入更多且更有彈性的內容。

  • 檢視網頁原始碼比較結果

    https://ithelp.ithome.com.tw/upload/images/20230923/20162805wHJWYKWKdo.png

  • ⚠️如果同時使用 fallbackTag<template #fallback> ... </template>,只會渲染 <template #fallback> ... </template> 的內容。

  • 如果想使用其他自訂 Components 作為預設畫面,可使用 <template #fallback> <SomeComponent /> </template>;無法使用 fallbackTag 達成(僅能放入 HTML Tag)。


.client & .server

除了可以透過上述的 <clientOnly> 來指定特定元素僅在客戶端渲染之外,還可以透過 Components 名稱加上後綴 .client;而相對的,若是加上後綴 .server 的元件則會僅在伺服器端渲染。

分別建立 components/Sidebar.server.vuecomponents/Comments.client.vue

// app.vue
<template>
  <Sidebar />
  <Comments />
</template>

🌞 Upcoming

接連幾天介紹 Nuxt 3 的各種函式和元件,明天開始會介紹 Nuxt 3 的 Pages 和 Routing,敬請期待!


參考資料

Components Directory
ClientOnly


上一篇
Day 8 – Nuxt 3 Components(元件)
下一篇
Day 10 - Nuxt 3 Pages & Routing(頁面及路由)
系列文
Nuxt 3 初學者指南:30天從基礎到實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言