主要是针对vue3.2中的<script setup>语法
这次这个项目使用的是一个 vue3.2+vite+antd vue
因为这个项目中多处使用到表格组件,所以进行了一个基础的封装,主要是通过antd vue 中表格的slots
配置项,通过配合插槽来进行封装自定义表格;
子组件的代码
<template>
<!-- 表格组件 -->
<a-table
:dataSource="dataSource"
:columns="columns"
class="ant-table-striped mar_t10"
size="small"
:pagination="false"
:scroll="tableHeight"
:rowClassName="
(record, index) => (index % 2 === 1 ? 'table-striped' : null)
"
:row-key="(record) => `${record[rowkey]}`"
:row-selection="
isSelect
? {
selectedRowKeys: selectedRowKeys,
onChange: onRowSel,
}
: null
"
>
<template v-slot:[item]="scope" v-for="item in renderArr">
<!-- // 插槽后面-slot:[item] 如果是动态渲染插槽需要使用这种方式
//renderArr 是父组件传递过来的用了插槽的名字,等下会在父组件中讲清楚,通过这个数组来遍历生成插槽 -->
<!-- //再通过这个插槽传递数据给父组件,做一些编辑提交的操作等等 -->
<slot :name="item" :scope="scope" v-bind="scope || {}"></slot>
</template>
</a-table>
</template>
<script lang="ts" setup>
// 把setup放在 script 标签里面,相当于 setup()语法糖, 具体可以看vue的官网
import { useSlots } from "vue";
// 如果要知道使用插槽的实例需要引入 useSlots
defineProps({
dataSource: {
type: Object,
required: true,
},
columns: {
type: Object,
required: true,
},
isSelect: {
type: Boolean,
required: true,
},
rowkey: {
type: String,
required: true,
},
});
// defineProps是3.2中新的语法,不需要从 vue里面引入出来
const slots = useSlots();
const emit = defineEmits(["onSelRowKeys"])
// 插槽的实例
const renderArr = Object.keys(slots);
const state = reactive({
selectedRowKeys: [] as (string | number)[],
});
const onRowSel = (selectedRowKeys: (string | number)[], selectedRows) => {
state.selectedRowKeys = selectedRowKeys;
emit("onSelRowKeys", selectedRowKeys)
};
// 此处减去的190是其他固定元素块的总高度
const tableHeight = ref({ x: 4800, y: document.body.clientHeight - 190 });
onMounted(() => {
// 监听浏览器窗口变化
window.onresize = () => {
return (() => {
tableHeight.value.y = document.body.clientHeight - 190;
})();
};
});
// 渲染的数据
const { selectedRowKeys } = toRefs(state);
</script>
<style lang="less" scoped>
.ant-table-striped :deep(.table-striped) td {
background-color: #fafafa;
}
</style>
里面最主要的就是通过useSlots
来知道父组件在使用表格组件的时候使用了几个插槽,通过返回的这个对象来通过Object.Keys 来遍历渲染生成新的插槽.
父组件的使用
//rowkey是唯一值随自己数据而修改
<template>
<MyTable :loading="loading"
:columns="columns"
:dataSource="viewList"
:isSelect="isSelect"
@onSelRowKeys="onSelRowKeys"
rowkey="xxxxxxxxxxx">
<template v-slot:bodyCell="{ scope }">
<span v-if="scope.column.key === 'action'" class="recent_linkcolor" @click="onDel(scope.record.fnid, 'nor')" >{{ $t("common.del") }}</span >
</template>
</MyTable>
</template>
<script setup>
const isSelect=ref(false)
const state=reactive({
rowKeys :[]
})
const dataSource = ref([])
const columns = [
{
title: '序号',
dataIndex: 'numbers',
key: 'numbers',
width: '6%'
},
{
title: '资源名称',
dataIndex: 'ResourceName',
slots: { customRender: 'ResourceName' }, //slots这个是重点,通过这个相当于告诉表格组件我有一个具名插槽要用,名字就是customRender后面的名字, 父组件中的useSlots插槽的实例就有这个ResourceName,下面也一样
width: '12%'
},
{
title: '资源名称IP',
dataIndex: 'IP',
slots: { customRender: 'IP' },
width: '12%'
},
{
title: '数据库类型',
dataIndex: 'DatabaseType',
slots: { customRender: 'DatabaseType' },
width: '12%'
},
{
title: '数据库名',
dataIndex: 'Dbname',
slots: { customRender: 'Dbname' },
width: '12%'
},
{
title: '用户名',
dataIndex: 'Username',
slots: { customRender: 'Username' },
width: '12%'
},
{
title: '端口',
dataIndex: 'Port',
slots: { customRender: 'Port' },
width: '12%'
},
{
title: '操作',
isSlot: true,
dataIndex: 'action',
slots: { customRender: 'action' }
}
]
const onSelRowKeys = (rowKeys: (string | number)[]) => {
state.rowKeys = rowKeys;
};
const changePage=()=>{
console.log('xxxx')
}
const onDel=()=>{
console.log('xxxx')
}
const {rowKeys }=toRefs(state)
</script>