【2024】作为前端开发,必须掌握的 Vue3 的 5 个组合式 API 方法
关注公众号,“技术干货”及时!「引言」:2024 你还不知道 Vue3 的 defineProps、defineEmits、defineExpose、defineOptions 和 defineSlots 吗?这几个 Vue3 组合式 API 方法不仅开发常用(涉及组件通信、组件复用等),在面试中也是不可或缺的一部分!掌握这些方法将有助于我们更深入地理解和运用 Vue 3 的组合式 API,这篇文章做了详细的技术点总结(直接复制使用即可)和经验分享,如果你也有好的分享,欢迎评论区一起讨论。
前言在 Vue3 中,defineProps、defineEmits、defineExpose、defineOptions、defineSlots是一组新的功能函数,用于定义组件的属性、事件、暴露、选项和插槽。
函数名称用途基本用法备注defineProps定义组件的属性(props)const props = defineProps({...});提供了基本的属性和事件处理通信功能defineEmits定义组件可以发出的事件const emit = defineEmits([...]);同上defineExpose定义组件暴露给父组件的方法或属性defineExpose({...});提供了更高级的组件封装能力,适合需要高度自定义和复用的组件。defineOptions在组合式 API 中设置组件的选项defineOptions({...});提供了在组合式 API 中设置组件选项的能力,适用于复杂组件或者需要大量配置的场景。defineSlots定义和访问组件的插槽内容const slots = defineSlots();简化了插槽内容的处理,适合需要动态内容和复杂布局的组件。以下详细列举了如何在开发中使用这些新的功能函数,并分享了一些扩展。如果有任何问题,请随时告知,我会及时帮助指正。
使用示例与分析1. defineProps:定义组件属性在 Vue 3 中,通过 defineProps 函数可以声明和验证组件的属性,使得父子组件之间数据的传递更加安全和可控。
适用于需要明确定义和验证输入属性的组件,特别是在使用 TypeScript 等类型系统时,能够提供良好的类型推断和验证。简化了属性定义和验证流程,但是对于简单的属性传递,可能显得有些繁琐,特别是在不需要严格验证的情况下。
例如,假设我们有一个简单的计数器组件,它接收一个初始计数值作为属性:
!--Counter.vue--
template
div
p{{count}}/p
button@click="increment"Increment/button
/div
/template
scriptsetup
import{ref}from'vue';
//定义属性
constprops=defineProps({
initialCount:{
type:Number,
required:true
}
});
//使用属性
constcount=ref(props.initialCount);
functionincrement(){
count.value++;
}
/script
父组件
!--Parent.vue--
template
div
Counter:initialCount="count"/
/div
/template
scriptlang="ts"setup
import{ref}from'vue';
importCounterfrom'./Counter.vue';
constcount=refnumber(100);
/script
2. defineEmits:定义组件事件defineEmits 允许组件明确声明它可以触发的事件,提供了一种类型安全的事件处理机制,替代了传统的 $emit 方法。
适用于需要明确定义和管理组件事件的场景,尤其是在复杂的组件通信和状态管理中尤为有用。例如,我们可以扩展我们的计数器组件,使其在计数值变化时发出事件,被父组件接收到。
!--Counter.vue--
template
div
p{{count}}/p
button@click="handleIncrement"Increment/button
/div
/template
scriptsetup
import{ref}from'vue';
//定义属性
constprops=defineProps({
initialCount:{
type:Number,
required:true
}
});
//定义事件
constemit=defineEmits(['update:count']);
constcount=ref(props.initialCount);
functionhandleIncrement(){
count.value++;
emit('update:count',count.value);
}
/script
父组件
!--Parent.vue--
template
div
Counter:initialCount="count"@update:count="handleCountUpdate"/
/div
/template
scriptlang="ts"setup
import{ref}from'vue';
importCounter'./Counter.vue'
constcount=refnumber(100)
functionhandleCountUpdate(value:number){
console.log(value)
}
/script
defineProps(定义组件属性)与defineEmits(定义组件事件)这两个组合式 API,是我们在 Vue3 组件通信常用的方法之一。
3. defineExpose:暴露给父组件的方法或属性defineExpose 函数允许组件开发者明确定义哪些内部方法或属性可以被父组件访问和调用,增强了组件的封装性和复用性。
适用于需要向外部暴露特定方法或属性的组件,使得父子组件之间的通信更加直接和有效。提高了组件的封装性和可复用性,但是可能会暴露过多的内部实现细节,所以使用时需要注意暴露方法。
我们继续修改我们的计数器组件,使其暴露一个重置计数值的方法:
!--Counter.vue--
template
div
p{{count}}/p
button@click="increment"Increment/button
/div
/template
scriptsetup
import{ref}from'vue';
//定义属性
constprops=defineProps({
initialCount:{
type:Number,
required:true
}
});
//定义事件
constemit=defineEmits(['update:count']);
constcount=ref(props.initialCount);
functionincrement(){
count.value++;
emit('update:count',count.value);
}
functionresetCount(){
count.value=props.initialCount;
}
//暴露方法
defineExpose({
reset:resetCount
});
/script
现在,父组件可以通过引用调用子组件的 reset 方法:
!--Parent--
template
Counterref="counter":initialCount="10"@update:count="handleCountUpdate"/
button@click="resetCounter"ResetCounter/button
/template
scriptlang="ts"setup
import{ref}from'vue';
importCounterfrom'./Counter.vue';
constcounter=ref(null);
functionhandleCountUpdate(value){
console.log(value);
}
functionresetCounter(){
counter.value.reset();
}
/script
「请注意:defineExpose[...] 定义的方法或者属性,由父组件来使用。但是,必须配合在父组件设置 ref 来使用。」
4. defineOptions:设置组件选项defineOptions 函数允许在组合式 API 中设置组件的选项,如 name、components 和 directives,使得在组合式 API 中使用类似于选项式 API 的配置。
适用于需要在组合式 API 中使用选项式 API 的配置方式的场景,尤其是对于复杂组件的配置和管理非常有帮助。提供了类似于选项式 API 的配置方式,增强了组件的配置灵活性和可扩展性。但是对于简单的组件可能显得过于复杂,不适合所有场景。
defineOptions({
name:'ComponentName',
components:{...},
directives:{...}
});
下面,我们来定义一个包含子组件和自定义指令的组件:
!--ParentComponent.vue--
template
divv-focus
p{{message}}/p
ChildComponent/
/div
/template
scriptsetup
importChildComponentfrom'./ChildComponent.vue';
constmessage=ref('HellofromParentComponent');
//定义选项
defineOptions({
name:'ParentComponent',
components:{
ChildComponent
},
directives:{
focus:{
mounted(el){
el.focus();
}
}
}
});
/script
5. defineSlots:处理组件插槽defineSlots 函数用于定义和访问组件的插槽内容,简化了在组合式 API 中处理动态内容和复杂布局的逻辑。
适用于需要动态内容和复杂布局的组件,能够提升组件的灵活性和可重用性。简化了插槽内容的处理逻辑,但目前在实际应用中用到的场景相对较少,对于简单的插槽处理可能显得过于复杂。
这里有一个例子,展示了如何在子组件中根据不同的插槽名和默认插槽,访问和处理多个插槽内容:
!--SlotComponent.vue--
template
div
divclass="header"
slotname="header"/slot
/div
divclass="content"
slot/slot
/div
divclass="footer"
slotname="footer"/slot
/div
/div
/template
scriptsetup
import{defineSlots}from'vue';
constslots=defineSlots();
console.log('HeaderSlotcontent:',slots.header?slots.header():'Noheadercontent');
console.log('DefaultSlotcontent:',slots.default?slots.default():'Nodefaultcontent');
console.log('FooterSlotcontent:',slots.footer?slots.footer():'Nofootercontent');
/script
在父组件中使用插槽:
!--ParentComponent.vue--
template
div
SlotComponent
template#header
h2HeaderSlot/h2
/template
template#footer
pFooterSlot/p
/template
/SlotComponent
/div
/template
scriptsetup
importSlotComponentfrom'./SlotComponent.vue';
/script
适用场景总结defineProps 和 defineEmits:这两者多配合使用,适用于简单组件和快速开发,因为它们提供了基本的属性和事件处理功能。
defineExpose:适用于高度封装和复用性要求,它提供了更高级的组件封装能力,可以将子组件的能力暴露出去给父组件。
defineOptions:适用于复杂组件和高级配置,它提供了在组合式 API 中设置组件选项的能力,适用于复杂组件或者需要大量配置的场景。
defineSlots 适用于插槽处理和动态内容,它简化了对于插槽内容的处理。
扩展1. vue3 与 ESLint在使用 Vue 3 和 ESLint 时,可能需要配置 ESLint 以识别 Vue 3 的组合式 API 函数。这可以通过在 ESLint 配置文件中添加全局变量声明来实现。以下是一个示例配置:
//.eslintrc.js
module.exports={
root:true,
env:{
node:true,
browser:true,
es2021:true
},
parser:'vue-eslint-parser',
extends:[
'eslint:recommended',
'plugin:vue/vue3-strongly-recommended'
//'standard'
],
parserOptions:{
ecmaVersion:12,
parser:'@typescript-eslint/parser',
sourceType:'module'
},
plugins:[
'vue',
'@typescript-eslint'
],
rules:{
quotes:[1,'single'],
'vue/script-setup-uses-vars':0,
'vue/no-multiple-template-root':'off',
'no-unused-vars':0,
camelcase:0,
'no-undef':0,
'vue/max-attributes-per-line':['error',{
singleline:{
max:3
},
multiline:{
max:3
}
}]
},
globals:{
withDefaults:true,
defineExpose:true,
defineEmits:true,
defineProps:true
}
}
这种配置告诉 ESLint 这些函数是全局的,并且是只读的(即不能重新赋值)。这将防止 ESLint 报告未定义的全局变量错误。
2. withDefaults辅助函数(很重要)建议在代码中,一定要配置 withDefaults。
withDefaults 是一个辅助函数,可以帮助在定义组件属性时设置默认值,使得组件属性在没有传递值时有一个预设的默认值。这样可以简化代码,避免在每个属性上都手动设置默认值。
而且由于 withDefaults 可以帮助定义属性的类型和默认值,使得 TypeScript 能够正确地推断和检查组件的属性使用。
constprops=withDefaults(defineProps({
message:String,
count:{type:Number,default:0},
}));
或者
constprops=withDefaults(defineProps{
message:string,
count:number,
}(),{
message:'hello',
count:0
})
结论Vue 3 的组合式 API 为开发者提供了更多的灵活性和模块化能力。通过使用 defineProps、defineEmits、defineExpose、defineOptions 和 defineSlots,我们可以更加简洁和直观地定义和使用组件的属性、事件、暴露方法、选项和插槽。
希望本文能帮助你深入理解 Vue 3 的组合式 API 函数。在评论区分享你的见解或提出问题,让我们一起探讨和学习!
关注公众号,“技术干货”及时!
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线