iT邦幫忙

2024 iThome 鐵人賽

DAY 17
1
Modern Web

Vue 3 初學者:用實作帶你看過核心概念系列 第 17

Vue 3 用實作帶你看過核心概念 - Day 17:組件基礎 - 全局註冊與區域註冊

  • 分享至 

  • xImage
  •  

文章背景圖

目錄

  • 定義組件的兩種方式 - SFC 單文件組件與 CDN 版本
  • 組件註冊的兩種方式 - 全域註冊與區域註冊
  • 結論

應用拆分組件官網架構圖

Day 5 我們提到可以將應用拆分為根組件和多個組件實例,並將功能模塊化。

今天,我們將更深入探討拆分組件帶來的優點:

  1. 提高程式碼的可複用性:通過將功能拆分為獨立的組件,可以在不同的地方重複使用相同的組件,減少重複的程式碼。
  2. 避免單一檔案過大:將功能劃分到不同的組件中,可以使每個組件的程式碼保持精簡和專注,避免單一檔案變得過於龐大和難以維護。
  3. 易於管理及協作:當項目中的各個功能被拆分到不同的組件時,開發者可以更輕鬆地管理每個組件的程式碼,並且在團隊協作時,每個人可以專注於不同的組件,減少衝突和相互依賴。
  4. 元件功能獨立化:每個組件專注於完成一項特定的功能,使得組件之間的依賴性降低,從而提高了應用程式的穩定性和可測試性。

定義組件的兩種方式 - SFC 單文件組件和 CDN 版本

  1. 使用構建工具(EX:Webpack、Vite)的單文件組件:SFC 是 Vue 提供的.vue文件格式,它將模板、相關邏輯處理和樣式封裝在一個文件中,便於開發、維護和測試。這種方式適合大型項目和複雜應用,具有良好的模塊化和擴展性。

這邊透過一個簡單的案例,帶大家熟悉一下SFC組件的使用方式:

流程說明:

  1. 定義 Title.vue 子組件顯示 title 響應式變數定義的訊息
  2. 透過匯入(import)的方式,在父組件匯入 Title.vue 子組件並使用區域註冊,顯示子組件的內容在模板上

Title.vue(子組件):

<script>
export default{
  data(){
    return{
      title: 'hello vue!'
    }
  }
}
</script>

<template>
  {{ title}}
</template>

將組件匯入至 App.vue(根組件)的使用場景如下:

<script>
import Title from './title.vue'

export default{
  components: { Title }
}
</script>

<template>
  <Title />
</template>

⭐ 官方建議透過駝峰式(PascalCase)命名方式定義組件名稱,並可搭配自閉合標籤使用(EX:<Title />),以便與原生 HTML 元素區分開來。


  1. 使用瀏覽器解析搭配 CDN 的方式:適合輕量級項目或快速原型開發。可以直接在 HTML 文件中引用 Vue 的 CDN 連結,讓瀏覽器進行解析與執行。

使用 CDN 定義組件模板內容的方式有兩種:

  • 可以將模板內容直接寫在template 參數中,以內聯的方式定義組件。
  • 可以透過<template>標籤來定義,並使用ID 綁定的方式引用該模板內容。

👉 Vue3 Options API 組件使用基礎(搭配 Vue CDN)實作連結

子組件方式 1(內聯方式)在 javascript 透過template 參數定義模板內容:

const childComponentA = {
  template: `<div> 我是 childComponent 模板(內聯版本)</div>`
};

子組件方式 2(javascript 透過ID 綁定特定 DOM 元素顯示,通常是template 標籤)
Vue Template:

<template id="childComponentB">
  <p>我是 childComponent 模板(HTML ID 綁定)</p>
</template>

javascript:

const childComponentB = {
  template: "#childComponentB"
};

根組件匯入上面透過內聯透過ID綁定DOM元素顯示的子組件顯示在根組件模板內容上:

<div id="app">
  <child-component-a></child-component-a>
  <child-component-b></child-component-b>
</div>

⭐ 瀏覽器解析組件方式,組件名稱只能使用kebab-case(串燒)的命名方式,並且必須使用非自閉合標籤(如:)。

javascript 根組件區域註冊子組件:

const rootComponent = {
  // 組件名稱:對應的組件實例
  components: { childComponentA, childComponentB }
};

組件註冊的兩種方式 - 全域註冊與區域註冊

Vue 組件都需要經過註冊,才可以在其他組件中匯入使用,而註冊方式又分成以下兩種:

  • 全域註冊:在 Vue 應用中將子組件進行全域註冊,這樣所有組件都可以隨時匯入使用。這種方式的缺點有兩個:
    1. 全域註冊的組件依賴關係變得複雜且難以追蹤。
    2. 即使某些全域註冊的組件未被實際使用,仍然會被打包進最終的文件中,從而增加打包後的檔案大小。
  • 區域註冊:在 Vue 組件中進行區域註冊,子組件僅能在當前父組件中使用,無法在其他組件中直接引用。這種方式僅在實際使用子組件時才會將其打包進最終文件中,這樣依賴關係更加明確,同時也能有效減少打包後檔案體積的增加風險。

👉 Vue3 Options API 全局註冊跟區域註冊實作連結

全域註冊與區域註冊差別範例圖

我們對同一個子組件分別使用區域註冊和全域註冊的方式來比較它們的差異:

子組件 Vue Template:

<template id="childComponentA">
  <div>我是 childComponent A</div>
</template>

子組件 javascript:

const childComponentA = {
  template: "#childComponentA"
};

父組件及 Vue 全域註冊 javascript:

// 根組件
const rootComponent = {
  // 區域註冊方式(在組件內註冊)
  components: { childComponentAA: childComponentA }
};

const app = createApp(rootComponent);
// 全域註冊方式(在 Vue 應用程式註冊)
app.component("childComponentA", childComponentA);

父組件 Vue Template:

<div id="app">
  <child-component-a></child-component-a>
  <child-component-a-a></child-component-a-a>
</div>

以下內容介紹使用Vue CLI預設構建的專案,透過單文件組件(SFC)的形式,並以全域區域方式註冊組件。
Vue CLI 預設專案架構

接下來,我們將<TheWelcome>從根組件中分離,並在Vue 應用中進行全域註冊。同時,對比全域註冊與原先使用區域註冊對於最終打包檔案大小的影響。
調整 Vue CLI 初始專案架構 TheWelcom 組件從區域註冊改全域測試展示圖

<TheWelcome>組件比較全域註冊與區域註冊的 tree shaking 結果如下:

  1. 全域註冊 <TheWelcome> 組件,未在模板中使用。打包後文件大小:64.41 KB。
  2. 全域註冊 <TheWelcome> 組件,並在模板中使用。打包後文件大小:64.82 KB。
  3. 區域註冊 <TheWelcome> 組件,未在模板中使用。打包後文件大小:55.08 KB。
  4. 區域註冊 <TheWelcome> 組件,並在模板中使用。打包後文件大小:64.37 KB。

可以觀察到即使全域註冊組件未實際使用在模板的情況下,仍然會打包進去文件當中。
區域註冊使用 tree shaking 移除未用到的組件

結論

  • 組件模組化功能:通過將功能拆分到不同的組件中,可以確保每個組件的職責單一,避免單一文件過於龐大。這種方法可以提高了程式碼的可讀性,也能讓後續維護和管理更加輕鬆。
  • 定義組件的方式
    • 搭配建構工具構建SFC 單文件組件:建議使用駝峰式命名,這樣更容易區分原生HTML 標籤Vue 組件標籤SFC 組件支持使用自閉合標籤,這使得模板語法可以更簡潔。
    • 透過瀏覽器解析搭配CDN:由於瀏覽器的解析規則,組件名稱必須使用串燒(kebab-case)命名方式,且不能使用自閉合標籤。瀏覽器僅對特定標籤如 和 < img /> 等自閉合標籤提供支持。
  • 組件註冊的方式
    • 區域註冊:組件僅在註冊的父組件中可用,這樣可以清晰地掌握其依賴關係。如果註冊的組件未被使用,打包時會自動忽略,減少不必要的代碼負擔。
    • 全域註冊:組件可以在整個 Vue 應用中使用,但這也使得其依賴關係較難追蹤。即使全域註冊的組件未被實際使用,它們仍然會被打包進最終的檔案中,增加打包文件的大小的風險。

上一篇
Vue 3 用實作帶你看過核心概念 - Day 16:使用 ref 屬性引用模板元素
下一篇
Vue 3 用實作帶你看過核心概念 - Day 18:父組件向子組件傳值 - props
系列文
Vue 3 初學者:用實作帶你看過核心概念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言