Vue3的組件有三種代碼組織方式
- 純Option API (不含setup)
- option API + setup
- 純 setup (即composition API)
對于這三種形式,設(shè)置基類的方法也略有不同工闺。
使用 mixins聊替、extends
vue3提供了 mixins和extends蕉毯,但是嘗試之后發(fā)現(xiàn)這兩種方法只支持純OptionAPI第煮,設(shè)置的data會被識別健爬,但是設(shè)置的setup里return 的 reactive佩耳,完全無效砂竖,setup也沒有被執(zhí)行真椿。
所以這種方式只能使用于第一種方式。
使用 hooks (function乎澄、class)
既然官方?jīng)]有提供突硝,那么我們自己來想想辦法。我們先觀察一下組件的代碼(第二種情況):
<template>
<!--模板-->
舉例
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'ui-core-',
components: {
// 注冊共用組件
},
props: {
// 定義共用屬性
},
setup(props, context) {
// 各種共用操作
_logger()
_setTitle()
// 共用成員
const foo = reactive ({})
return {
foo
}
}
})
</script>
defineComponent 方法接收一個對象置济,對象需要有特定的幾個屬性解恰,比如name、components浙于、props护盈、setup等。
那么也就是說羞酗,我們可以做一個函數(shù)返回這樣的對象即可腐宋。
比如我們先建立一個js(或則ts)文件:
export function base (name, callback) {
return {
name: 'ui-' + name,
components: {
// 注冊共用組件
},
props: {
// 定義共用屬性
},
setup(props, context) {
// 各種共用操作
_logger()
_setTitle()
// 共用成員
const foo = reactive ({})
// 執(zhí)行其他操作
const re = callback(props, context)
return {
foo,
...re
}
}
}
}
有點(diǎn)像模板模式。
傳入name和一個回調(diào)函數(shù),props, context作為參數(shù)進(jìn)行傳遞胸竞。內(nèi)部成員也可以作為參數(shù)傳遞欺嗤。
這樣一個簡單的基類就做成了,如果你覺得function不好看卫枝,那么可以換成class煎饼。
export default class BaseComponent {
name: string
components: any
props: any
setup: any
constructor (name: string, callback: (props: any, context: any) => any) {
this.name = name
this.components = {}
this.props = {}
this.setup = (props: any, context: any) => {
// 各種共用操作
_logger()
_setTitle()
// 執(zhí)行其他操作
const re = callback(props, context)
return {
...re
}
}
}
}
有了class之后,還可以設(shè)置子類校赤,不過感覺有點(diǎn)繁瑣吆玖。總之痒谴,反正可以實(shí)現(xiàn)就對了衰伯。
script setup怎么辦
上述這種方法應(yīng)該也是可以支持純composition API的铡羡,但是有點(diǎn)小問題积蔚,defineProps 和 defineEmits 并不是普通 js 函數(shù),而是一種“宏”烦周。
引用官網(wǎng)的解釋:
defineProps 和 defineEmits 都是只能在 <script setup> 中使用的編譯器宏尽爆。他們不需要導(dǎo)入,且會隨著 <script setup> 的處理過程一同被編譯掉读慎。
也就是說 defineXXX系列 只有在 <script setup> 標(biāo)簽內(nèi)部才會被識別漱贱,如果在單獨(dú)的js文件里面,不會被識別夭委。
這就導(dǎo)致 defineProps 和 defineEmits 無法做成基類的形式幅狮。
如果需要的基類不涉及 defineProps 和 defineEmits 的話,那么還是可以在單獨(dú)的js文件里面定義一個function或者class的株灸,(即做一個綜合的hooks)崇摄。
如果涉及 defineProps 和 defineEmits,那么慌烧,我也沒想出來辦法逐抑。(只能第二種方式)