Vue 3 更新了許多組件中的語法,包括生命周期、filter、setup、teleport 等
為了介紹這些特性,需要先了解一下 Vue 組件的基本玩法
這篇文章介紹的內容基本都是沿用 Vue 2 的語法,只在一些細節上有所調整
一、單檔案組件
通過 Vue.createApp() 創建的應用,可以使用 component 方法創建自定義組件
const app = Vue.createApp({});
app.component('my-component', {
data() {
return {
name: 'Wise.Wrong'
}
},
template: `<div>hello {{name}}</div>`,
});
不過在實際專案中,都是使用“單檔案組件”,也就是以 .vue 檔案的形式開發
比如上面組件,改寫成單檔案組件就是這樣的:
<template>
<div>hello {{ name }}</div>
</template>
<script lang="ts">
/* 當前檔案路徑: src/components/my-component.vue */
import { defineComponent } from 'vue';
export default defineComponent({
name: 'MyComponent',
data() {
return {
name: 'Wise.Wrong',
};
},
});
</script>
這里的 data 必須通過函式的形式回傳一個物件,而不能直接使用物件
// 2.x 可以接收物件,但 3.x 的 data 只能是 function
假如現在還有另一個組件 <home> ,我們希望在 <home> 組件中使用 <my-component>
可以直接在 <home> 中引入 my-component.vue 檔案,然后通過 components 屬性注冊組件

上面的代碼中,我在 components 中使用的是大駝峰命名組件,而在 <template> 中使用的是短線命名
這是因為 HTML 本身不區分大小寫,Vue 更建議我們在 DOM 中使用全小寫的短線命名的方式
二、Props
現在我們有了一個父組件 <home> 與子組件 <my-component>
如果我想在父組件中向子組件傳遞引數,可以通過 Props
首先在子組件定義 props

然后父組件傳入對應的 props 屬性值
![]()
最終結果

除了定義陣列形式的 props 之外,還可以使用物件型別,這樣就能對 props 做更多限制
export default defineComponent({
// ...
props: {
likes: String, // 僅限定型別
years: {
type: [String, Number],
required: true, // 必填
},
info: {
type: Object,
default: () => ({ // 物件和陣列型別的默認值只能用函式回傳
title: '這里是物件型別的 prop',
}),
},
type: {
// 自定義校驗函式
validator: (val: string) => (
['success', 'warning', 'danger'].indexOf(val) !== -1
),
},
},
// ...
});
如果父組件傳參不符合子組件中 props 定義的規則,Vue 會在控制臺拋錯
更多關于 Props 的使用可以查看官方檔案
三、無狀態組件
在子組件中,props 和 data 一樣都是直接掛載到 this 物件下的,可以通過 this.xxx 的方式取值
對于某些功能型組件,只需要 props 不需要 data,比如這樣的一個提示框組件:
<template>
<div :class="['alert', type]">
<div class="alert-content">{{content}}</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Alert',
props: ['type', 'content'],
});
</script>
![]()

這種只接收 props,沒有定義 data、methods、computed 等回應資料的組件,被稱為無狀態組件
在 Vue 2 中,無狀態組件的初始化比普通組件快得多,所以經常會作為性能優化的一個考量
為了創建一個無狀態組件,必須在 <template> 中宣告 functional
<template functional>
Vue 2
</template>
但是在 Vue 3 中,無狀態組件不再需要宣告 functional
只需要像一個普通組件一樣定義,只是不要添加 data 等回應資料,就像上面的提示框組件那樣
官方檔案是這樣解釋的:
However, in Vue 3, the performance of stateful components has improved to the point that the difference is negligible.
但是,在Vue 3中,有狀態組件的性能已提高到比肩無狀態組件的程度,
emmmmmm... 相當的膨脹...
不過我喜歡~
四、Mixin
與無狀態組件相對應的是有狀態組件,也就是帶有 data 等回應資料的組件,我們作業中寫的組件大部分都是有狀態組件
而隨著業務的不斷擴大,整個應用變得非常臃腫,這時候組件共用和邏輯抽取就尤為重要,這時候可以使用 mixin
假如我們有三個組件,它們的 js 部分都包含以下內容:
<script>
export default {
// ...
data() {
return {
// ...
company: {
name: 'Perfect World',
address: 'Chongqing China',
},
loading: false,
}
},
props: {
// ...
title: String
},
methods: {
// ...
fetchCompanyInfo(data) {
this.loading = true;
return fetch('/api')
.then(res => res.json())
.then(res => {
this.company = { ...res.data };
})
.finally(_ => {
this.loading = false;
})
}
},
};
</script>
三個組件都包含回應資料(data) loading 和 company,以及相應的查詢方法(methods) fetchInfo,還有一個來自父組件的引數(props) title
這些邏輯完全一樣,如果要在三個組件中各寫一份完全一樣的代碼,就會非常難受,不利于維護
有了 mixin 之后,我們就能把這些邏輯寫在一個物件里面并匯出
/* mixin-test.js */
export default {
data: () => ({
loading: false
}),
props: {
title: String
},
methods: {
fetchCompanyInfo(data) {
// ...
}
}
}
然后在需要用到這部分邏輯的組件中引入,并注冊到 mixins
mixins 接收的是一個陣列,也就是說可以同時注冊多個 mixin
<script>
import MixinTest from "./mixin/mixin-test.js";
export default {
// ...
mixins: [ MixinTest ],
};
</script>
Vue 在初始化組件的時候,會將引入的 mixin 物件和當前組件進行合并
在合并的時候如果遇到了同名選項,對于不同的型別 (data、props、methods) 會有不同的策略
1. 如果是 props、methods、components、directives 沖突,會以組件本身的鍵值對覆寫 mixin
2. 對于生命周期這樣的鉤子函式出現沖突,會先觸發 mixin 中的鉤子函式,然后觸發組件中的鉤子函式
3. 如果 data 發生沖突,將執行淺層次的合并:
const Mixin = {
data: ()=> ({
user: { name: 'Jack', id: 1 }
})
}
const Comp = {
mixins: [Mixin],
data: () => ({
user: { id: 2 }
})
}
// 最終的結果是:
{
user: { id: 2 }
}
而在 Vue 2 中,data 會執行深層次的合并,上例的結果會變成:
{
user: { id: 2, name: 'Jack' }
}
在 Vue 2 的時代,Mixin 是封裝的共用邏輯的常用手段,但這種方式一直都受到很多開發者的質疑
首先就是 mixin 的重名問題,雖然 Vue 有一套合并策略(這個合并策略可以自定義)來處理 mixin 的重名問題
但組件內部是無法知道 mixin 到底提供了哪些欄位,如果后來的維護人員不熟悉組件中的 mixin,在維護代碼的時候很容易因為重名的問題導致 bug
而且 mixin 可以使用組件中的資料,如果維護組件的時候更改了 mixin 所依賴的資料,也會導致 bug
為了解決這些問題,Vue 3 推出了 Composition API ,用函式式編程的思想來封裝組件邏輯
欲知 Composition API 如何,請聽下回分解~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/143271.html
標籤:其他
上一篇:用原生JS寫冒泡排序及影片演示
下一篇:WEB 之 HTML 系列筆記
