DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能示例4,TableView15_04导出当前页数据示例
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕
目录
- DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能示例4,TableView15_04导出当前页数据示例
-
- 📚前言
- 📚页面效果
-
- 📘组件代码 \src\components\Table\Table.vue
- 📘组件代码 \src\views\TableView15_04.vue
- 📚代码测试
- 📚测试代码正常跑通,附其他基本代码
-
- 📘编写路由 src\router\index.js
- 📘编写展示入口 src\App.vue
- 📚页面效果
📚📗📕📘📖🕮💡📝🗂️✍️🛠️💻🚀🎉🏗️🌐🖼️🔗📊👉🔖⚠️🌟🔐⬇️·正文开始
⬇️·🎥😊🎓📩😺🌈🤝🤖📜📋🔍✅🧰❓📄📢📈 🙋0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟🆗*️⃣#️⃣
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能示例4,TableView15_04导出当前页数据示例
📚前言
- 低成本训练:DeepSeek-V3使用14.8万亿Token训练,成本仅558万美元(约2000块NVIDIA H800芯片,耗时55天),远低于同类模型。
- 动态知识蒸馏:结合“知识蒸馏-反馈强化”循环机制,知识更新周期缩短至72小时,效率较传统季度级更新提升12倍。
📚页面效果
📘组件代码 \src\components\Table\Table.vue
<!-- components/Table/Table.vue -->
<template>
<div
class="ds-table"
:class="[`table-size-${size}`, { 'table-stripe': stripe, 'table-border': border }]"
ref="tableRef"
expandable
>
<!-- 导出按钮 -->
<div v-if="showExport" class="table-export">
<button @click="handleExport">
{
{ exportButtonText }}
</button>
</div>
<!-- 加载遮罩层 -->
<div v-if="loading" class="loading-mask">
<div class="loading-content">
<slot name="loading">
<div class="default-loading">
<div class="loading-spinner"></div>
<div class="loading-text">{
{ loadingText }}</div>
</div>
</slot>
</div>
</div>
<!-- 搜索框 -->
<div v-if="showSearch" class="search-container">
<input
v-model="searchKeyword"
placeholder="搜索..."
@input="handleSearch"
class="search-input"
:disabled="loading"
/>
</div>
<!-- 表格容器 -->
<div class="table-container" :style="{ height: fixedHeader ? fixedHeaderHeight : 'auto' }">
<!-- 表头固定容器 -->
<div v-if="fixedHeader" class="fixed-header-container">
<table class="header-table" ref="headerTableRef">
<colgroup>
<col v-if="rowSelection" :style="{ width: selectionColumnWidth }">
<col v-for="col in columns" :key="col.dataIndex" :style="{ width: col.width || 'auto' }">
</colgroup>
<thead>
<tr>
<!-- 选择列 -->
<th
v-if="rowSelection"
:class="headerAlignClass"
class="selection-column"
>
<div class="header-content">
<input
type="checkbox"
:checked="allSelected"
@change="toggleAllSelection"
:disabled="loading"
/>
</div>
<div
v-if="resizable"
class="resize-handle"
@mousedown.prevent="startResize('selection', $event)"
></div>
</th>
<!-- 数据列 -->
<th
v-for="(col, colIndex) in columns"
:key="col.dataIndex"
:class="[headerAlignClass, { sortable: sortable && col.sortable }]"
>
<div class="header-content">
<slot :name="`header-${col.dataIndex}`" :column="col">
<span @click="handleSort(col)">
{
{ col.title }}
<span v-if="sortable && col.sortable" class="sort-icon">
{
{ sortedColumn.field === col.dataIndex ?
(sortedColumn.order === 'asc' ? '↑' : '↓') : '' }}
</span>
</span>
</slot>
</div>
<div
v-if="resizable"
class="resize-handle"
@mousedown.prevent="startResize(colIndex, $event)"
></div>
</th>
</tr>
</thead>
</table>
</div>
<!-- 数据表格容器 -->
<div class="body-container" @scroll="syncHeaderScroll">
<table class="body-table" ref="bodyTableRef">
<colgroup>
<col v-if="rowSelection" :style="{ width: selectionColumnWidth }">
<col v-for="col in columns" :key="col.dataIndex" :style="{ width: col.width || 'auto' }">
</colgroup>
<!-- 空状态 -->
<tbody>
<tr v-if="showEmpty" class="empty-row">
<td :colspan="totalColumns">
<slot name="empty">
<div class="empty-content">
<svg class="empty-icon" viewBox="0 0 1024 1024">
<path d="M832 320H192v448h640V320z m-64 384H256V384h512v320z m64-416h-64v-64h64v64z m0-128H192v64h640v-64zM128 256h64v512H128z m704 512h64V256h-64v512z"/>
</svg>
<div class="empty-text">{
{ emptyText }}</div>
</div>
</slot>
</td>
</tr>
<!-- 数据行 -->
<template
v-for="(row, index) in currentPageData"
:key="rowKey ? row[rowKey] : index"
>
<tr
:class="{
'selected-row': isRowSelected(row),
'stripe-row': stripe && index % 2 === 0
}"
@click="handleRowClick(row)"
>
<!-- 选择列 -->
<td
v-if="rowSelection"
:class="cellAlignClass"
>
<input
type="checkbox"
:checked="isRowSelected(row)"
@change="toggleRowSelection(row)"
:disabled="loading"
/>
</td>
<!-- 数据列 -->
<td
v-for="col in columns"
:key="col.dataIndex"
:class="cellAlignClass"
>
<!-- 如果是树形数据,添加缩进 -->
<template v-if="treeData && col.dataIndex === 'name'">
<span
class="tree-indent"
:style="{ paddingLeft: `${row._level * 20}px` }"
></span>
</template>
<slot :name="`cell-${col.dataIndex}`" :row="row" :value="row[col.dataIndex]">
{
{ row[col.dataIndex] }}
</slot>
</td>
</tr>
<!-- 展开行 -->
<tr v-if="expandable && expandedKeys.includes(row.id)" class="expanded-row">
<td :colspan="columns.length + (rowSelection ? 1 : 0)">
<slot name="expanded-row" :row="row"></slot>
</td>
</tr>
</template>
</tbody>
</table>
</div>
<div
v-if="resizing"
class="resize-line"
:style="{ left: resizeLinePos + 'px' }"
></div>
</div>
<!-- 分页 -->
<div v-if="pagination" class="table-pagination">
<button
:disabled="currentPage === 1 || loading"
@click="changePage(currentPage - 1)"
>
上一页
</button>
<span>第 {
{ currentPage }} 页 / 共 {
{ totalPages }} 页</span>
<button
:disabled="currentPage >= totalPages || loading"
@click="changePage(currentPage + 1)"
>
下一页
</button>
</div>
</div>
</template>
<script setup>
import {
ref,
computed,
watch,
toRefs,
onMounted,
onBeforeUnmount,
nextTick
} from 'vue'
import {
utils, writeFile } from 'xlsx' // 需要安装xlsx库
const props = defineProps({
// 数据相关
data: {
type: Array,
default: () => []
},
columns: {
type: Array,
default: () => []
},
pagination: {
type: Boolean,
default: false
},
pageSize: {
type: Number,
default: 10
},
currentPage: {
type: Number,
default: 1
},
// 样式相关
stripe: Boolean,
border: Boolean,
size: {
type: String,
default: 'medium',
validator: v => ['small', 'medium', 'large'].includes(v)
},
headerAlign: {
type: String,
default: 'left',
validator: v => ['left', 'center', 'right'].includes(v)
},
cellAlign: {
type: String,
default: 'left',
validator: v => ['left', 'center', 'right'].includes(v)
},
// 功能相关
rowSelection: Boolean,
selectedRows: {
type: Array,
default: () => []
},
sortable: Boolean,
sortedColumn: {
type: Object,
default: () => ({
field: null, order: null })
},
// 其他配置
rowKey: String,
virtualScroll: Boolean,
showSearch: Boolean,
emptyText: {
type: String,
default: '暂无数据'
},
// loading
loading: {
type: Boolean,
default: false
},
loadingText: {
type: String,
default: '