Vue3 setup 写法最佳实践
两种方式最终都能满足我们搭建组件的需求,但经过实践setup() 形式的组件往往要比SFC 形式的组件多出很多代码且不易维护,下面我会阐述出案例以证实结论
我们先来看 组合式 setup()
<template>
<Select v-model:value="selectValue" />
</template>
<script lang="ts">
import { ref } from 'vue'
import { getBusinessByProject } from '@/api/versionControl/business'
import { KeyItem, RES_CODE } from '@/type'
import { Key } from 'ant-design-vue/es/_util/type'
import { SelectValue } from 'ant-design-vue/lib/select'
export default {
props: {
value: {
type: String,
default: '',
},
},
emits: ['eventBusinessChange'],
setup() {
const options = ref<KeyItem[]>([])
const selectValue = ref<SelectValue>(undefined)
const loading = ref(false)
const getData = async (key: Key): Promise<void> => {
try {
loading.value = true
const res = await getBusinessByProject({ project: key })
loading.value = false
const { status, data } = res || {}
if (status !== RES_CODE.SUCCESS) return
options.value = data || []
} catch (error) {
loading.value = false
console.error('getData->', error)
}
}
// 返回值会暴露给模板和其他的选项式 API 钩子
return {
selectValue,
getData,
options,
}
},
mounted() {
console.log(this.getData) // 0
},
}
</script>
看完上述代码给我感受:
1.类型声明过于繁琐
2.emits 声明只能 声明函数,而不能具体到具体到函数入参与返回值
3.通过return的方式将所有变量和函数都暴露出去了,这样的方式每声明一个变量或者函数模版渲染中所需,都需要暴露出去,如果是一个复杂且状态较多的组件,这样的方式就会变得难以维护
4.return 所暴露出去的函数与变量再父组件往往不需要那么多,对于一个刚入门vue3同学,这样的方式可能会导致大量无用的变量暴露而这些变量其实是无用的,久而久之代码就会变得难以维护…
看完了 组合式 setup 我们再来看看SFC setup
<template>
<Select
v-model:value="selectValue"
/>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { Select } from "ant-design-vue";
interface MyProps {
data?: ApiQoData;
needAssert?: boolean;
}
const props = withDefaults(defineProps<MyProps>(), {
needAssert: () => true,
data: () => {
return {} as ApiQoData;
},
});
interface MyEmit {
(e: "eventBusinessChange", key: Key, option: KeyItem): void;
}
const emit = defineEmits<MyEmit>();
const options = ref<KeyItem[]>([]);
const selectValue = ref<SelectValue>(undefined);
const loading = ref(false);
const getData = async (key: Key): Promise<void> => {
try {
loading.value = true;
const res = await api({ project: key });
loading.value = false;
const { status, data } = res || {};
if (status !== RES_CODE.SUCCESS) return;
options.value = data || [];
} catch (error) {
loading.value = false;
console.error("getData->", error);
}
};
defineExpose({
getData
});
</script>
SFC形式的setup给我们的感觉 模块化更清晰,类型声明更清晰,暴露变量函数也会更简单易维护,这样的方式也更加靠近函数式编程
<script setup>
是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。相比于普通的
更少的样板内容,更简洁的代码。
能够使用纯 TypeScript 声明 props 和自定义事件。
更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。