iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0
Modern Web

欸你是要進 Vue 了沒?系列 第 27

欸你是要進 Vue 了沒? - Day27:Vue 組件基礎之 Component 的定義 && 使用 && 註冊

  • 分享至 

  • xImage
  •  

Hello 大家蠔,今天我們來學習 Vue 的核心概念:組件。

分別會帶到這些內容:

  • 定義一個組件
    構建步驟定義的組件 - 單文件組件
    使用物件導出定義的組件
  • 使用組件
    導入的組件是獨立的
    組件的命名
  • 組件註冊
    全局註冊
    局部註冊

/images/emoticon/emoticon65.gif
/images/emoticon/emoticon65.gif

一起來看吧~

定義一個組件

組件的英文是 Component,來看看解釋

a part that combines with other parts to form something bigger
組成部分;成分;零件

英文的解釋好像比較有感覺,就像積木、零件,從大部分拆分出來的小部分的意思。

也來看看官方文件怎麼說:

組件允許我們將 UI 劃分為獨立的、可重用的部分,並且可以對每個部分進行單獨的思考。在實際應用中,組件常常被組織成層層嵌套的樹狀結構:
image

「單獨的思考」這點,像在寫 JS 的時候,會思考將複雜邏輯拆分成小的步驟,簡化結構、利於維護。而 Vue 組件的底層邏輯也是基於這個概念去建構的,當我們將一個大的功能或 UI 拆分成多個組件時,就可以讓程式碼更有組織。

而 Vue 組件有不同的結構,我們一起來看看~

構建步驟定義的組件 - 單文件組件

官方文件:當使用構建步驟時,我們一般會將 Vue 組件定義在一個單獨的 .vue 文件中,這被叫做單文件組件 (簡稱 SFC)。

讓我們複習一下我們在 Day3 講到的單文件組件(SFC)的概念:
在 Vue 裡,我們可以將功能拆分成各個獨立的組件,將渲染的模板、資料邏輯與 CSS 樣式封裝在單個文件中,而這些單個文件各自擁有 <template><script><style> 的結構。

也就是很常見的 .vue 檔案結構。

官方的範例:

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>

<script><template> 是必要區塊,<style> 區塊是非必要的)

export default

SFC 會默認導出為 ES module。
於編譯時,SFC 會交由 @vue/compiler-sfc 編譯成 JavaScript 和 CSS,而編譯後的每個 SFC 都會成為 ES module,這也就是為什麼我們可以無腦的使用 import 的方式引入它們。

這裡補充一下,export 的兩種導出方法:具名導出 和 默認導出。(默認導出是 SFC 的常用方式,稍後我們會再介紹~)

使用物件導出定義的組件

不使用 SFC 結構的組件,通常會是一個 .js 檔,並且會以export 導出自身結構。

先看一下官方的範例:

import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    return { count }
  },
  template: `
    <button @click="count++">
      You clicked me {{ count }} times.
    </button>`
  // 也可以針對一個 DOM 內聯模板:
  // template: '#my-template-element'
}

以這種方式的組件結構通常:

  1. 是一個 .js 檔。
  2. 使用 export 將自身導出為 ES module。
  3. setup(){} 區塊定義資料邏輯。
  4. 而在這裡的 template 可以有兩種方式定義:
  • 使用 字串。
  • 使用 ID 選擇器來指向一個元素 (通常會指向 html 檔案中的 <template> 元素)。

使用組件

官方文件:我們會在接下來的指引中使用 SFC 語法,無論你是否使用構建步驟,組件相關的概念都是相同的。示例一節中展示了兩種場景中的組件使用情況。

因此我們跟著官方的腳步,接下來都會以 SFC 的使用方式來說明哦!

要使用一個 SFC 組件,我們可以在 <script setup> 中 import 它。

例如:我們定義一個 componentParent.vuecomponentChild.vue
並於 componentParent.vue 中使用 componentChild.vue

// componentChild.vue

<script setup>
import { ref } from "vue";

const count = ref(0);
</script>
<template>
  <button @click="count++">我是一個計數器:{{ count }}</button>
</template>

01

componentParent.vue 中於 <script setup> import 它:

// componentParent.vue

<script setup>
import ComponentChild from "./componentChild.vue";
</script>
<template>
  <ComponentChild />
  <ComponentChild />
  <ComponentChild />
</template>

這邊可以注意:

  1. <script setup> 中 import 子組件後,於模板中就可以使用。
  2. 導入的子組件可以「重複」使用。
  3. 以大駝峰作為 SFC 的命名。
  4. /> 關閉標籤。

看一下在瀏覽器上的畫面:

導入的組件是獨立的

這時候會發現,三個按鈕都互不相干!

可以理解到:每個被導入的組件都是一個個體,不會互相干擾彼此的狀態,而這也是因為:每當我們使用一個組件,就會創造一個新的實例。
渲染器遇到這三個子組件,而每個子組件都會遵循自己的生命週期過程,因此也確保了:組件的重用性和狀態的隔離。

組件的命名

在導入組件時,官方推薦使用大駝峰(PascalCase)命名 SFC,這樣可以更容易與原生 HTML 元素做區分。

例如:

// 在 .vue 檔案中

<MyComponent />

但若需要在原生 HTML 中導入,就需要以 kebab-case 烤肉串的形式來定義,另外也會需要有 closing tag。

// 在 HTML 檔案中

<my-componet></my-componet>

但 Vue 可以辨認這兩種不同的命名格式,將它們視為同一個組件。
所以使用 大駝峰命名的 SFC,可以於 HTML 中以 烤肉串命名格式 直接導入。

官方文件:Vue 支援 PascalCase 和 kebab-case 互通:

PascalCase 註冊的組件可以在模板中使用 或 標籤進行引用。

組件註冊

官方文件:一個 Vue 組件在使用前需要先被“註冊”,這樣 Vue 才能在渲染模板時找到其對應的實現。組件註冊有兩種方式:全局註冊和局部註冊。

全局註冊

全局註冊組件的特性:

  1. 所有的 Vue 組件都可以直接在模板中引用這個已經註冊的組件,不需要在每個組件內單獨 import。
  2. 彼此之間可以互相使用。
  3. 組件未被使用,還是會在打包後被留下,不會自動移除。
  4. 組件之間有較多的依賴關係。

語法

.component('要使用在模板中的組件名稱',組件的實現)

若我們要註冊 SFC 組件,實際會像這樣子:

// main.js
	
import { createApp } from 'vue';
import App from './App.vue';
import MyComponent from './components/MyComponent.vue';  // 導入 SFC 組件 MyComponent

const app = createApp(App);

// 全局註冊 MyComponent
app.component('MyComponent', MyComponent);

app.mount('#app');

在這邊我們做了:

  1. import { createApp } 創建實例的方法。
  2. import 根組件 App.vue、子組件 MyComponent.vue
  3. 將根組件創建實例,存到變數 app
  4. app.component('MyComponent', MyComponent);
    app 實例上全局註冊導入的 MyComponent 這個組件,並會在模板中以 'MyComponent' 這個名稱使用它。
  5. app 根組件的實例掛載到 HTML 結構中 id 為 app 的位置。

而每個註冊後的實例 app.component() 會 return 自己,所以當註冊多個 SFC 組件,可以使用「鏈式語法」來達成:

// main.js
	
import { createApp } from 'vue';
import App from './App.vue';
import MyComponentA from './components/MyComponentA.vue';
import MyComponentB from './components/MyComponentB.vue'; 
import MyComponentC from './components/MyComponentC.vue';  
const app = createApp(App);

// 全局註冊 MyComponentA, MyComponentB, MyComponentC
app.component('MyComponentA', MyComponentA)
   .component('MyComponentB', MyComponentB)
   .component('MyComponentC', MyComponentC);

app.mount('#app');

局部註冊

局部註冊組件的特性:

  1. 只能在有導入的地方使用,因此在每個組件內都需要單獨 import。
  2. 組件未被使用,會在打包後自動被移除。
  3. 組件之間的依賴關係相對明確。

而在使用 <script setup> 的 SFC 中,導入的組件可以直接在模板中使用,不需要註冊:

<script setup>
import ComponentA from './ComponentA.vue'
</script>

<template>
  <ComponentA />
</template>

若沒有使用 SFC 的話,就需要以 .component() 的方式來註冊:

import ComponentA from './ComponentA.js'

export default {
  components: {
    ComponentA: ComponentA 
    // key 為 '要使用在模板中的組件名稱',value 組件的實現。
  },
  setup() {
    // ...
  }
}

keyvalue 名稱相同,可以使用 ES2015 的縮寫語法:

// ES2015 的縮寫語法,縮寫為 ComponentA
import ComponentA from './ComponentA.js'

export default {
  components: {
    ComponentA
  },
  setup() {
    // ...
  }
}

小結

今天算是概念篇,但看文件時還是覺得暈頭轉向 XD 邊走路邊和朋友解釋今天寫了什麼,就順便順了邏輯,把學到的東西講出來有更有印象惹。

image

import 我文章的小結 from '朋友的小結';

鐵人賽來到倒數了!
明天要學什麼,明天再告訴大家,但還是明天見喔。
/images/emoticon/emoticon37.gif

範例 code ⬇️

https://github.com/Jamixcs/2024iThome-jamixcs/tree/main/src/components/day27

參考資料


上一篇
欸你是要進 Vue 了沒? - Day26:Vue 模板引用之使用 ref 直接操作 DOM 的小小法術
下一篇
欸你是要進 Vue 了沒? - Day28:Vue 組件間的溝通方式之 Props、defineProps() 來自父組件の快遞請收下
系列文
欸你是要進 Vue 了沒?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言