1.二次封装的组件所有数据由父组件传过来,只是作为容器与具体的业务数据不挂钩
2.尽可能的适应大多数的场景,少数场景可拓展
【1 如何解决外部组件给内部组件的传递参数问题:
如果选择defineProps的话,参数太多,写出的代码非常冗杂
- 因此利用
$attrs来传,他可以拿到props没传的属性
【2 处理插槽传递的问题
-
如何处理多个插槽的传递
-
并且要传了哪些插槽用哪些
v-for遍历+$slots属性 ($slots可拿到一个对象,对象中的属性就是外部传过来的插槽) -
- 然后根据这些属性动态生成封装组件中的
<template> - 再通过
<slot>映射出来
- 然后根据这些属性动态生成封装组件中的
【3 因为要保证二次封装组件的可拓展性,可能组件有时候要暴露一些方法,所以要解决如何接收方法的问题
- 用
ref获取自己封装的组件的实例再由defineExpose()暴露出去
原来的代码是这样的:
<a-table
:columns="columns"
:data-source="meetingRoomResult"
:pagination="false"
>
<template v-slot:bodyCell="{ column, record }">
<!-- 预订详情 -->
<template v-if="column.dataIndex === 'isBooked'">
<MeetingRoomBookingModal :meetingRoomNameFirst="record.name" />
</template>
<!-- 创建时间 -->
<template v-if="column.dataIndex === 'createTime'">
<div>{{ formatTime(record.createTime) }}</div>
</template>
<!-- 更新时间 -->
<template v-if="column.dataIndex === 'updateTime'">
<div>{{ formatTime(record.updateTime) }}</div>
</template>
<!-- 操作 -->
<template v-else-if="column.dataIndex === 'operate'">
<a-popconfirm
title="你确定要删除吗"
cancel-text="No"
ok-text="Yes"
@confirm="confirm(record.id)"
@cancel="removeMeetingRoom"
>
<a-tag color="red">删除</a-tag>
</a-popconfirm>
<!-- <div > -->
<a-tag color="blue" @click="showModal(record.id)">更新</a-tag>
<!-- </div> -->
</template>
</template>
</a-table>
<div class="pagination">
<a-pagination
v-model:current="pageNo"
:total="(totalCount / pageSize) * 10"
show-less-items
/>
</div>
现在是这样的:
这是二次封装的组件
<!-- 对列表和分页器组件的二次封装 -->
<template>
<div>
<a-table v-bind="$attrs" ref="tableRef">
<!-- 这里#[value]是在动态指定插槽名,slotData是要传给对应插槽的数据 -->
<template v-for="(key,value) in $slots" #[value]="slotData">
<!-- slot作为一个插槽出口来接收外部组件传来的插槽 -->
<slot :name="value" v-bind="slotData || {}"></slot>
</template>
</a-table>
<a-pagination show-less-items v-bind="$attrs" class="pagination" ref="paginationRef"></a-pagination>
</div>
</template>
<script setup lang="ts">
import { Pagination, Table } from 'ant-design-vue';
import { ref } from 'vue';
const tableRef = ref<InstanceType<typeof Table>>()
const paginationRef = ref<InstanceType<typeof Pagination>>()
defineExpose({
tableRef,
paginationRef
})
</script>
这是用组件的地方
<PageList
:total="(totalCount / pageSize) * 10"
v-model:current="pageNo"
:columns="columns"
:data-source="meetingRoomResult"
:pagination="false"
>
<template v-slot:bodyCell="{ column, record }">
<!-- 预订详情 -->
<template v-if="column.dataIndex === 'isBooked'">
<MeetingRoomBookingModal :meetingRoomNameFirst="record.name" />
</template>
<!-- 创建时间 -->
<template v-if="column.dataIndex === 'createTime'">
<div>{{ formatTime(record.createTime) }}</div>
</template>
<!-- 更新时间 -->
<template v-if="column.dataIndex === 'updateTime'">
<div>{{ formatTime(record.updateTime) }}</div>
</template>
<!-- 操作 -->
<template v-else-if="column.dataIndex === 'operate'">
<a-popconfirm
title="你确定要删除吗"
cancel-text="No"
ok-text="Yes"
@confirm="confirm(record.id)"
@cancel="removeMeetingRoom"
>
<a-tag color="red">删除</a-tag>
</a-popconfirm>
<!-- <div > -->
<a-tag color="blue" @click="showModal(record.id)">更新</a-tag>
<!-- </div> -->
</template>
</template>
</PageList>