主要方法:https://blog.csdn.net/m0_57391092/article/details/119191630
第一天:
父组件:index.vue
搜索组件:SearchBar.vue
表格组件:TableList.vue
表格组件里的数据通过:
defineExpose({
showCols,
})
暴露出去。
const showCols = computed(() => {
return {
productShowCols: toRaw(TabMapDataSource[TabsEnum.REGISTER].showColumns), //注册信息
batchShowCols: toRaw(TabMapDataSource[TabsEnum.BATCH].showColumns) // 批次信息
}
})
父组件中通过:
<TableList
ref="tableListRef" //总的ref
/>
const tableListRef = ref()
来接收总的ref。
父组件中通过tableListRef.value.showCols拿到数据:
/**
* 导出excel
*/
const exportExcel = (callback) => {
// callback()
console.log(tableListRef.value.showCols, tableListData) //表头和数据
}
//表单总数
const tableListData = reactive({
[TabsEnum.REGISTER]: {}, //注册表格信息
[TabsEnum.BATCH]: {} //批次表格信息
})
searchbar组件中通过引入导出excel所需的包:
import ExportJsonExcel from 'js-export-excel'
// 导出按钮,通过调用方法发出自定义事件
<div class="search-right" @click="exportExcel"><a-button>导出</a-button></div>
// 发出自定义事件,将封装的方法给父组件
const exportExcel = () => {
Emit('exportExcel', exportFunc)
}
父组件通过exportExcel自定义事件来触发方法,他接收了封装的方法作为参数:
const exportExcel = (callback) => {
// callback()
}
第二天:
可以选择字段导出:
父组件拿到searchBar子组件发送的自定义事件,接收了mode(选择当前还是全部字段)和导出excel的回调函数作为参数;通过selectCols添加注册信息和批次信息的数组,通过switch语句选择是当前字段还是全部字段,把注册信息和批次信息数组处理成向后端发送的格式,然后拼接到condition里,通过exportInfo调用接口拿到返回数据,解构出data,放到回调函数里执行。
<template>
<SearchBar @exportExcel="exportExcel" @handleSearch="handleSearch" :filter="filter" :frameFilters="frameFilters" />
<TableList
ref="tableListRef"
:loading="refreshTable.loading"
@changeTab="changeTab"
@changePagination="changePagination"
:currentTab="currentTab"
:tableListData="tableListData"
/>
</template>
<script setup lang="ts">
import SearchBar from './components/SearchBar.vue'
import TableList from './components/TableList.vue'
/**
* tab 相关
*/
const currentTab = reactive({ value: TabsEnum.REGISTER }) //当前tab是注册还是批次
// 导入请求接口
import {
getExportColumnsData,
getExportProd
} from '@/api/material'
// 导入ts类型
import {
// 当前字段还是全部字段
exportExcelModeEnum
} from '@/views/register/registration-and-batch-info-query/types'
const tableListRef = ref() // 拿到TableList组件导出的内容
const globalSearchInfo = ref(initSearchInfo())
/**
* 导出接口
*/
const exportInfo = {
// 注册的接口
[TabsEnum.REGISTER]: {
method: getExportProd,
prefixName: t('register.registrationAndBatchInfoQuery.queryViewDetail.product')
},
// 批次的接口
[TabsEnum.BATCH]: {
method: getExportColumnsData,
prefixName: t('register.registrationAndBatchInfoQuery.queryViewDetail.batch')
}
}
/**
* 导出
*/
const exportExcel = async (mode, callback: Function) => {
let condition = {}
let selectCols = {
productShowCols: [],
batchShowCols: []
}
// 判断是当前字段还是所有字段
switch (mode) {
// 如果是当前字段
case exportExcelModeEnum.CURRENT_SHOW: {
// 拿到注册和批次表格头
const { productShowCols, batchShowCols } = tableListRef.value.showCols
// 过滤一下数组然后放到selectCols里面
seletCols.productShowCols = deBuildColumns(productShowCols)
seletCols.batchShowCols = deBuildColumns(batchShowCols)
// 拼接对象
condition = Object.assign({}, globalSearchInfo.value, seletCols)
break
}
// 如果是全部字段
default: {
condition = Object.assign({}, globalSearchInfo.value, tableListRef.value.currentAllCols)
break
}
}
// 调用接口
const { data } = await exportInfo[currentTab.value].method(condition)
// 调用回调
callback(data, { fileName: `${exportInfo[currentTab.value].prefixName}_${treeNodeData.value.name}` })
}
</script>
// 注册信息还是批次信息
export enum TabsEnum {
REGISTER = 1, // 注册
BATCH //批次
}
// 当前字段还是全部字段
export enum exportExcelModeEnum {
ALL,
CURRENT_SHOW
}
export function initSearchInfo(): SearchInfo {
return {
keyword: '',
sortColumn: '',
pageSize: 10,
pageNum: 1,
filter: {
frameId: '',
frameName: '',
productName: '',
batchName: '',
batchParams: [],
productCustomParams: [],
batchCustomParams: []
},
productShowCols: [],
batchShowCols: []
}
}
export const deBuildColumns = (columns) => {
columns = columns || []
return columns.map((column) => ({
name: column.title,
key: column.dataIndex,
type: column.type
}))
}
用户点击按钮触发下拉菜单,触发handleSelectExportExcelMode方法,选择导出全部字段还是当前字段(exportExcelModeEnum),在方法中触发exportExcel(exportExcelMode.value)的调用;exportExcel方法中发送了一个exportExcel自定义事件给父组件,将exportExcelMode,exportFunc作为参数传递。
<template>
<div class="search-right">
<!--用户选择时触发handleSelectExportExcelMode方法-->
<a-dropdown @select="handleSelectExportExcelMode">
<a-button>导出</a-button>
<template #content>
<!--value是选项值-->
<a-doption :value="exportExcelModeEnum.CURRENT_SHOW">导出Excel(当前字段)</a-doption>
<a-doption :value="exportExcelModeEnum.ALL">导出Excel(全部字段)</a-doption>
</template>
</a-dropdown>
</div>
</template>
<script setup lang="ts">
import { exportExcelModeEnum } from '@/views/register/registration-and-batch-info-query/types'
import ExportJsonExcel from 'js-export-excel'
const Emit = defineEmits(['handleSearch', 'exportExcel'])
/**
* 导出excel文件
*/
const exportExcelMode = ref(exportExcelModeEnum.ALL)
const handleSelectExportExcelMode = (value) => {
exportExcelMode.value = value
exportExcel(exportExcelMode.value)
}
const exportFunc = (_data: Array<[]>, option: { [key in string]: any }) => {
let [targetHeader, sheetData]: [[], []] = [[], []]
const { fileName } = option
if (Array.isArray(_data) && _data.length > 0) {
const [firstArr] = _data.splice(0, 1)
targetHeader = firstArr
}
_data.forEach((items) => {
if (Array.isArray(items)) {
const targetRowInfo = {}
items.forEach((innerItem, index) => {
targetRowInfo[targetHeader[index]] = innerItem
})
sheetData.push(targetRowInfo as unknown as never)
}
})
const datas = [
{
sheetData,
sheetName: fileName,
sheetHeader: targetHeader,
sheetFilter: targetHeader
}
]
const toExcel = new ExportJsonExcel({
fileName,
datas
})
// 调用保存方法
toExcel.saveExcel()
}
const exportExcel = (exportExcelMode: exportExcelModeEnum) => {
Emit('exportExcel', exportExcelMode, exportFunc)
}
</script>
//组件内部维护的不同 tab 对应的信息
let TabMapDataSource = reactive({
[TabsEnum.REGISTER]: {
//展示的cols
showColumns: [],
//编辑的cols信息 (dataIndexArr)
selectShowColumns: []
},
[TabsEnum.BATCH]: {
showColumns: [],
selectShowColumns: []
}
})
const showCols = computed(() => {
return {
productShowCols: toRaw(TabMapDataSource[TabsEnum.REGISTER].showColumns),
batchShowCols: toRaw(TabMapDataSource[TabsEnum.BATCH].showColumns)
}
})
defineExpose({
selectedRowKeys,
showCols,
clearCacheData,
currentAllCols
})
defineExpose
我们从父组件获取子组件实例通过ref
<Menu ref="menus"></Menu>
const menus = ref(null)
然后打印menus.value 发现没有任何属性
这时候父组件想要读到子组件的属性可以通过 defineExpose暴露
const list = reactive<number[]>([4, 5, 6])
defineExpose({
list
})
这样父组件就可以读到了。