#子传父&父传子props和emits #封装的table #vue3
父组件:emits defineEmits props
子组件:
子组件
bash
<template>
<el-table v-bind="$attrs" ref="innerTableRef" v-loading="loading" border :data="tableData"
@sort-change="handleSortChange">
<el-table-column v-for="{
label,
prop,
type,
align,
width,
tooltip,
meta,
fixed,
reserveSelection,
sortable,
} in visibleColumns" :key="prop" :align="align ?? 'center'" :width="width" :label="label" :prop="prop"
:show-overflow-tooltip="tooltip ?? true" :type="type" :fixed="fixed" :reserve-selection="reserveSelection"
:sortable="sortable">
<template #default="{ row, column: { rawColumnKey } }">
<template v-if="type === 'operate'">
<div class="flex justify-evenly">
<slot :row="row" name="operate" />
</div>
</template>
<template v-else-if="prop">
<template v-if="type === 'radio'">
<el-radio v-model="radioVal" class="none-label" :label="row[prop]" @input="onRadioInput(row)" />
</template>
<template v-else-if="type === 'link'">
<template v-if="!meta">
<el-link class="cell-link" type="primary"
@click="$emit(`click${getFirstCharUpperCaseProperty(rawColumnKey)}`, row)">{{ row[prop] }}
</el-link>
</template>
</template>
<template v-else-if="type === 'tag' && meta">
<el-tag v-if="row[prop] != null" effect="dark" :type="getMetaType(row[prop], meta, 'tag')">
{{ getMetaLabel(row[prop], meta, 'tag') }}
</el-tag>
</template>
<template v-else-if="type === 'custom'">
<slot :name="rawColumnKey" :row="row" />
</template>
<span v-else>{{ row[prop] }}</span>
</template>
</template>
</el-table-column>
</el-table>
</template>
<script setup lang="ts">
const emits = defineEmits<{
sortChange: [data: { column: any, prop: string, order: any }]
}>()
// 表格排序改变事件
function handleSortChange(data: { column: any, prop: string, order: any }) {
emits('sortChange', data)
}
父组件
bash
<template>
<div class="bg-white rounded-md p-2.5 shadow">
<table-component v-model:page-index="queryParams.pageIndex" v-model:page-size="queryParams.pageSize"
:table-config="tableData.tableConfig" :table-data="tableData.data" :loading="tableData.loading"
:total="tableData.totalRows" @fetch="fetchData" @click-sys-uni-code="onClickCode" @sortChange="handleSortChange">
<template #btn>
<el-button v-permission="['production_processing:add']" :icon="Plus" type="primary" @click="onHeadEvent('add')">
添加
</el-button>
</template>
<template #operate="{ row }">
<el-link v-permission="['production_processing:input']" :icon="View" type="primary"
@click="onRow('input', row)">
{{ row.set == true ? '编辑' : '录入' }}
</el-link>
<el-link v-permission="['production_processing:delete']" :icon="Delete" type="danger"
@click="onRow('delete', row)">
删除
</el-link>
</template>
<template #status="{ row }">
<template v-if="row.status == ASSEMBLY_ATATUS.PROGRRESS">
<el-progress :text-inside="true" :stroke-width="15" :percentage="row.progressNumber" />
</template>
<template v-if="row.status == ASSEMBLY_ATATUS.NO">
<el-tag effect="dark" type="danger">未开始</el-tag>
</template>
<template v-if="row.status == ASSEMBLY_ATATUS.COMPLETED">
<el-tag effect="dark" type="success">已完成</el-tag>
</template>
<template v-if="row.status == ASSEMBLY_ATATUS.CLOSED">
<el-tag effect="dark" type="info">已关闭</el-tag>
</template>
</template>
<template #doneTimePreset="{ row }">
{{ row.doneTimePreset }}
<triangle border-color="red" title="超"
v-if="dateVal(nowDate) <= dateVal(row.doneTimePreset) || dateVal(row.doneTimePreset) <= dateVal(row.doneTimeFact)" />
</template>
<template #doneTimeFact="{ row }">
{{ row.doneTimeFact == '' ? '' : row.doneTimeFact.substring(0, 10) }}
<triangle border-color="red" title="超" v-if="dateVal(nowDate) <= dateVal(row.doneTimeFact)" />
</template>
</table-component>
</div>
<script setup lang="ts">
const queryParams = ref({
fBillNo: '', //订单编号
sysUniCode: '', //系统序列码
fMaterialNumber: '', //物料编号
fMaterialName: '', //物料名称
fMaterialSpecification: '', //规格型号
status: [] as number[], //状态 0未开始 1进行中 2已完成
srcProjectType: null, //源项目类型 1合同 2研发 3维修
srcSysUniCode: '', //源项目系统序列码
pageIndex: 1,
pageSize: 10,
outsource: false, //是否筛选加工外协
OrderBy: null,
Desc: true
})
const tableData = ref({
tableConfig: [
{
label: '序号',
type: 'index',
width: 60
},
{
label: '系统序列号',
prop: 'sysUniCode',
type: 'link'
},
{
label: '订单编号',
prop: 'fBillNo'
},
{
label: '物料编码',
prop: 'fMaterialNumber'
},
{
label: '物料名称',
prop: 'fMaterialName'
},
{
label: '规格型号',
prop: 'fMaterialSpecification'
},
{
label: '单位',
prop: 'fUnit',
width: '90'
},
{
label: '数量',
prop: 'fAmount',
width: '90'
},
{
label: '合格品入库数量',
prop: 'okInStock',
width: '130'
},
{
label: '进度',
prop: 'status',
type: 'custom',
width: '200'
},
{
label: '当前工序',
prop: 'currProcedure'
},
{
label: '预计完成时间',
prop: 'doneTimePreset',
type: 'custom',
sortable: 'custom',
},
{
label: '实际完成时间',
prop: 'doneTimeFact',
type: 'custom',
sortable: 'custom',
},
{
label: '来源项目',
prop: 'srcProjectType',
type: 'tag',
meta: {
tagConfig: [
{
label: '合同项目',
value: SOURCE_PROJECT.CONTRACT,
type: 'primary'
},
{
label: '研发项目',
value: SOURCE_PROJECT.RESEARCH,
type: 'warning'
},
{
label: '维修项目',
value: SOURCE_PROJECT.SERVICE,
type: 'danger'
}
]
}
},
{
label: '来源序列号',
prop: 'srcSysUniCode'
},
{
label: '操作',
type: 'operate',
width: 150
}
],
data: [],
loading: false,
totalRows: 0
})
// 排序
function handleSortChange(data: { prop: string, order: string }) {
console.log(data, 222)
// 有排序
if (data.order) {
console.log(data.prop, (data.prop === 'doneTimePreset' ? 1 : 2));
queryParams.value.OrderBy = (data.prop === 'doneTimePreset' ? 1 : 2)
queryParams.value.Desc = (data.order === 'descending')
} else {
// 没排序-使用默认排序
queryParams.value.OrderBy = null
}
// 还原成第一页并重新发起请求
queryParams.value.pageIndex = 1
fetchData()
}
怎么说呢还是得多看多写