前言
示例基于环境:vue3
、 typescript
在vue中通过自定义组件可以很好的来进行业务封装和复用。一个组件对外来讲主要有以下几个方面
- 属性
- 方法
- 事件
简单示例如下所示
父组件
<script setup lang="ts">
import { ref } from 'vue';
import HelloWorld from './components/HelloWorld.vue'
const helloWorldRef = ref<InstanceType<typeof HelloWorld>>()
function onClick() {
alert('catch click event')
}
function letSayHello() {
helloWorldRef.value.sayHello()
}
</script>
<template>
<input type="button" value="让自定义组件打招呼" @click="letSayHello" />
<HelloWorld ref="helloWorldRef" msg="Hello, this is a custom component demo"
@on-click="onClick"
/>
</template>
子组件
<script setup lang="ts">
// 对外定义属性
defineProps({
msg:String
})
// 对外定义事件
const emits = defineEmits(['on-click'])
// 对外定义方法
defineExpose({
sayHello
})
function sayHello() {
alert('hello')
}
function onClick() {
emits('on-click')
}
</script>
<template>
<div class="greetings">
<h1 class="green" @click="onClick">{{ msg }}</h1>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
}
</style>
详细介绍
defineProps
和defineEmits
API,它们将自动地在<script setup>
中可用defineProps
和defineEmits
都是只能在<script setup>
中使用的编译器宏。他们不需要导入,且会随着<script setup>
的处理过程一同被编译掉。- 传入到
defineProps
和defineEmits
的选项会从 setup 中提升到模块的作用域。因此,传入的选项不能引用在 setup 作用域中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块作用域内。
对外属性
对外属性是通过 defineProps
方法来完成的,完整用法如下所示
defineProps({
msg: {
// 是否必须属性
require: true,
// 属性类型
type: String,
// 默认值
default:''
}
})
对外方法
vue3中自定义组件可以很方便的对外暴露方法,通过 defineExpose
来完成对外方法的声明
defineExpose({
sayHello
})
function sayHello() {
alert('hello')
}
父组件调用方式
const helloWorldRef = ref<InstanceType<typeof HelloWorld>>()
....
helloWorldRef.value.sayHello()
对外定义事件
通过 defineEmits
来声明对外事件
子组件通过下面的方式完成事件的发布
emits('on-click')
父组件通过注册事件来响应事件
function onClick() {
alert('catch click event')
}
.....
<HelloWorld @on-click="onClick" />
结语
我们通过 定义属性 、 定义事件、 定义方法 就基本上可以完成对一个自定义组件的封装,可以完成父组件到子组件的数据传递(通过属性),也可以完成子组件到父组件的数据传递(通过事件) 也可以完成子组件能力的对外暴露(通过方法)
示例代码: https://gitee.com/bitlove/vue-demo/tree/main/custom-component