什么是组件?
在vue中,组件是可复用的Vue实例,用于封装和组合可重用的UI元素。组件可以包含模板、数据、方法和样式等,它们可以独立地管理自己的状态和行为,并可以在应用程序中多次使用。
一般组件的封装及使用
组件封装了自己的模板、数据和方法,可以隐藏实现细节,提供清晰的接口供其他组件使用。这样可以降低组件之间的耦合度,提高代码的可读性。
来看下一般的组件封装,以下用消息提示组件为例:
- 其中script部分,接收参数,向外暴露出方法。
ts
<script setup lang="ts">
import type { PropType } from 'vue'
const emit = defineEmits(['cancel', 'confirm'])
interface IConfig {
title: string
message: string
onConfirm?: Function
onCancel?: Function
}
defineProps({
config: {
type: Object as PropType<IConfig>,
default: () => {
return {
title: '',
message: ''
}
}
}
})
</script>
- html和css部分,使用参数并显示,以及样式的书写。
html
<template>
<view class="flex items-center justify-center absolute top-0 left-0 w-full h-full z-99999 bg-[#000000cc]">
<view class="w-4/5 h-[400rpx] bg-white rounded-lg p-3">
<view class="h-[260rpx] text-center">
<view class="font-semibold">{{ config.title }}</view>
<view>{{ config.message }}</view>
</view>
<view class="flex justify-between h-[100rpx]">
<button class="w-1/2 mr-1" @click="emit('cancel')">取消</button>
<button class="w-1/2 bg-[#2979ff] text-white" @click="emit('confirm')">确认</button>
</view>
</view>
</view>
</template>
如何使用呢?
- 引入组件并使用。
ts
import MessageBox from '@/components/MessageBox/index.vue'
html
<template>
<view class="flex items-center w-full h-[100vh]">
<view class="w-4/5 my-2 mx-auto">
<u-button @click="handleOpenMsg1" type="primary">一般组件</u-button>
</view>
<view class="w-4/5 my-2 mx-auto">
<u-button @click="handleOpenMsg2" type="primary">命令式组件</u-button>
</view>
<MessageBox v-if="isShow" :config="config" @cancel="isShow = false" @confirm="handleConfirm" />
</view>
</template>
- 定义变量及方法控制
ts
// 显示及配置
const isShow = ref<boolean>(false)
const config = ref({
title: '一般组件',
message: '这是内容'
})
// 点击显示
const handleOpenMsg1 = () => {
isShow.value = true
}
// 点击确认
const handleConfirm = () => {
console.log('确认');
isShow.value = false
}

总结:
通过以上我们可以看到,组件的封装并不麻烦,只需定义好模版接收参数等等就行了,但是一般在项目中组件通用性的居多,可能在一处使用还行,如果多处使用到同一种组件的使用,会不会发现组件在使用时较为复杂,需要引入组件,定义一大堆的变量和方法,给后续的使用维护增加了较大的负担。
如何改变?
像我们经常使用的elementUI这种框架一样,在使用消息提示框的时候直接这样写就很省事:
js
import { ElMessage } from 'element-plus'
ElMessage({
type: 'info',
message: '消息内容',
})
如何封装这样简单易用的组件呢?
还是以上面的消息提示为例,组件部分可以不用改变,在组件同级目录建一个ts文件:

需引入 createApp
将组件挂载到body中,在确认按钮或取消按钮执行后调用组件的移除。
取消事件可以不必传,默认点击关闭弹窗。当然这只是以消息组件作为示例,其他的组件封装也要考虑全面,使用起来方便即可。
ts
import MessageBox from './index.vue' // 引入组件
import { createApp } from 'vue'
interface IConfig {
title: string
message: string
onConfirm?: Function
onCancel?: Function
}
// 抛出使用方法
export default function showMsg(config: IConfig) {
const app = createApp(MessageBox, {
config, // 组件参数配置
onConfirm() { // 确认按钮事件
config.onConfirm && config.onConfirm(() => {
app.unmount()
div.remove()
})
},
onCancel() { // 取消按钮事件
if (config.onCancel) {
config.onCancel(() => {
app.unmount()
div.remove()
})
} else {
app.unmount()
div.remove()
}
}
})
const div = document.createElement('div')
document.body.appendChild(div)
app.mount(div)
}
如何使用
引入抛出的方法:
ts
import showMsg from '@/components/MessageBox';
点击按钮时调用即可:
ts
const handleOpenMsg2 = () => {
showMsg({
title: '命令式组件',
message: '测试内容',
onConfirm: (close: any) => {
console.log(11111);
close()
},
onCancel: (close: any) => {
console.log(22222);
close()
}
})
}

以上就是命令式组件的封装了。当然这也不是更简洁的封装,这里将组件的vue文件和ts文件分开了;更为一体化的封装则是将vue模版组件的内容通过JSX写入到ts文件中,和react中的写法类似,这里就不过多赘述了,感兴趣的前端小伙伴们可以去尝试一下哦!