如何封装更简单易用的命令式组件?
什么是组件?
在vue中,组件是可复用的Vue实例,用于封装和组合可重用的UI元素。组件可以包含模板、数据、方法和样式等,它们可以独立地管理自己的状态和行为,并可以在应用程序中多次使用。
一般组件的封装及使用
组件封装了自己的模板、数据和方法,可以隐藏实现细节,提供清晰的接口供其他组件使用。这样可以降低组件之间的耦合度,提高代码的可读性。
来看下一般的组件封装,以下用消息提示组件为例:
- 其中script部分,接收参数,向外暴露出方法。
1<script setup lang="ts">
2import type { PropType } from 'vue'
3
4const emit = defineEmits(['cancel', 'confirm'])
5interface IConfig {
6 title: string
7 message: string
8 onConfirm?: Function
9 onCancel?: Function
10}
11defineProps({
12 config: {
13 type: Object as PropType<IConfig>,
14 default: () => {
15 return {
16 title: '',
17 message: ''
18 }
19 }
20 }
21})
22</script>
23
- html和css部分,使用参数并显示,以及样式的书写。
1<template>
2 <view class="flex items-center justify-center absolute top-0 left-0 w-full h-full z-99999 bg-[#000000cc]">
3 <view class="w-4/5 h-[400rpx] bg-white rounded-lg p-3">
4 <view class="h-[260rpx] text-center">
5 <view class="font-semibold">{{ config.title }}</view>
6 <view>{{ config.message }}</view>
7 </view>
8 <view class="flex justify-between h-[100rpx]">
9 <button class="w-1/2 mr-1" @click="emit('cancel')">取消</button>
10 <button class="w-1/2 bg-[#2979ff] text-white" @click="emit('confirm')">确认</button>
11 </view>
12 </view>
13 </view>
14</template>
15
如何使用呢?
- 引入组件并使用。
1import MessageBox from '@/components/MessageBox/index.vue'
2
1<template>
2 <view class="flex items-center w-full h-[100vh]">
3 <view class="w-4/5 my-2 mx-auto">
4 <u-button @click="handleOpenMsg1" type="primary">一般组件</u-button>
5 </view>
6 <view class="w-4/5 my-2 mx-auto">
7 <u-button @click="handleOpenMsg2" type="primary">命令式组件</u-button>
8 </view>
9
10 <MessageBox v-if="isShow" :config="config" @cancel="isShow = false" @confirm="handleConfirm" />
11 </view>
12</template>
13
- 定义变量及方法控制
1// 显示及配置
2const isShow = ref<boolean>(false)
3const config = ref({
4 title: '一般组件',
5 message: '这是内容'
6})
7
8// 点击显示
9const handleOpenMsg1 = () => {
10 isShow.value = true
11}
12
13// 点击确认
14const handleConfirm = () => {
15 console.log('确认');
16 isShow.value = false
17}
18
总结:
通过以上我们可以看到,组件的封装并不麻烦,只需定义好模版接收参数等等就行了,但是一般在项目中组件通用性的居多,可能在一处使用还行,如果多处使用到同一种组件的使用,会不会发现组件在使用时较为复杂,需要引入组件,定义一大堆的变量和方法,给后续的使用维护增加了较大的负担。
如何改变?
像我们经常使用的elementUI这种框架一样,在使用消息提示框的时候直接这样写就很省事:
1import { ElMessage } from 'element-plus'
2
3ElMessage({
4 type: 'info',
5 message: '消息内容',
6})
7
如何封装这样简单易用的组件呢?
还是以上面的消息提示为例,组件部分可以不用改变,在组件同级目录建一个ts文件:
需引入 createApp
将组件挂载到body中,在确认按钮或取消按钮执行后调用组件的移除。
取消事件可以不必传,默认点击关闭弹窗。当然这只是以消息组件作为示例,其他的组件封装也要考虑全面,使用起来方便即可。
1import MessageBox from './index.vue' // 引入组件
2import { createApp } from 'vue'
3
4interface IConfig {
5 title: string
6 message: string
7 onConfirm?: Function
8 onCancel?: Function
9}
10
11// 抛出使用方法
12export default function showMsg(config: IConfig) {
13 const app = createApp(MessageBox, {
14 config, // 组件参数配置
15 onConfirm() { // 确认按钮事件
16 config.onConfirm && config.onConfirm(() => {
17 app.unmount()
18 div.remove()
19 })
20 },
21 onCancel() { // 取消按钮事件
22 if (config.onCancel) {
23 config.onCancel(() => {
24 app.unmount()
25 div.remove()
26 })
27 } else {
28 app.unmount()
29 div.remove()
30 }
31 }
32 })
33 const div = document.createElement('div')
34 document.body.appendChild(div)
35 app.mount(div)
36}
37
如何使用
引入抛出的方法:
1import showMsg from '@/components/MessageBox';
2
点击按钮时调用即可:
1const handleOpenMsg2 = () => {
2 showMsg({
3 title: '命令式组件',
4 message: '测试内容',
5 onConfirm: (close: any) => {
6 console.log(11111);
7 close()
8 },
9 onCancel: (close: any) => {
10 console.log(22222);
11 close()
12 }
13 })
14}
15
以上就是命令式组件的封装了。当然这也不是更简洁的封装,这里将组件的vue文件和ts文件分开了;更为一体化的封装则是将vue模版组件的内容通过JSX写入到ts文件中,和react中的写法类似,这里就不过多赘述了,感兴趣的前端小伙伴们可以去尝试一下哦!
上一篇:
Redux持久化全局状态管理最佳实践
下一篇:
ECMA 2019(ES10) 新特性
相关笔记