table組件示例
CustomTable.vue 子組件
<template>
<div class="report_table">
<!-- 表頭 -->
<div class="table_columns">
<div
class="cell"
v-for="item in props.columns"
:key="item.prop"
:style="{ width: item.width }"
>
{{ item.lable }}
</div>
</div>
<!-- 匯總 -->
<div class="summary">
<slot name="summary"></slot>
</div>
<!-- 內(nèi)容區(qū)域 -->
<div
class="table_source"
@scroll="
() => {
if (props.tableType === 1) {
handleScroll();
}
}
"
ref="tableRef"
v-if="props.dataSource.length"
>
<!-- 下拉刷新 -->
<van-pull-refresh
v-model="props.refreshLoading"
@refresh="emits('onRefresh')"
>
<div class="row" v-for="record in props.dataSource" :key="record.id">
<div
class="cell"
v-for="items in columns"
:key="items"
:style="{ width: items.width }"
>
<div class="cell_item" v-if="items.moneyType">
¥{{ record[items.prop] }}
</div>
<div class="cell_item" v-else>{{ record[items.prop] }}</div>
</div>
</div>
</van-pull-refresh>
</div>
<!-- 暫無內(nèi)容區(qū)域 -->
<div class="no_data" v-else>
<span class="data_text">暫無內(nèi)容</span>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const props = defineProps({
// 當前加載的table類型, 1. 滾動動態(tài)請求數(shù)據(jù) 2. 滾動不請求數(shù)據(jù)
tableType: {
type: Number,
default: null,
},
// 列表數(shù)據(jù)
dataSource: {
type: Array,
default: () => [],
},
// 列表字段
columns: {
type: Array,
default: () => [], // width 參數(shù)建議設置 百分比摸柄,設置百分比可自適應
},
refreshLoading: {
type: Boolean,
default: false,
},
total: {
type: Number,
default: 0,
},
});
const emits = defineEmits(["onRefresh", "onTableScroll"]);
const tableRef = ref(null);
// 上拉刷新
const handleScroll = () => {
// 變量scrollTop是滾動條滾動時导犹,距離頂部的距離
const scrollTop = tableRef.value.scrollTop;
// 變量scrollHeight是滾動條的總高度
const scrollHeight =
tableRef.value.scrollHeight;
// 變量clientHeight是滾動條可視區(qū)域的高度
const clientHeight =
tableRef.value.clientHeight;
// 當滾動條到達底部湖苞,并且距離底部小于10px時,加載數(shù)據(jù)
if (scrollTop + clientHeight >= scrollHeight) {
if (props.total > props.dataSource.length) {
emits('onTableScroll')
}
}
};
</script>
<style lang="scss" scoped>
.report_table {
width: 100%;
height: 0;
flex: 1;
background: #fff;
.table_columns {
width: 100%;
height: 50px;
font-weight: 400;
font-size: 15px;
color: #989898;
display: flex;
.cell {
height: 100%;
line-height: 50px;
text-align: center;
}
}
.summary {
width: 100%;
height: 50px;
border-top: 1px solid #efefef;
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.13);
display: flex;
color: #2c2c2c;
font-size: 15px;
}
.table_source {
height: calc(100% - 100px);
overflow: auto;
.row {
display: flex;
padding: 15px 0;
border-bottom: 1px solid #efefef;
.cell {
font-weight: 400;
font-size: 15px;
color: #2c2c2c;
text-align: center;
.cell_item {
width: 100%;
word-break: break-all;
}
}
}
}
.no_data {
width: 100%;
height: calc(100% - 100px);
background: #F6F6F6;
text-align: center;
.data_text {
display: inline-block;
margin-top: 50px;
}
}
}
</style>
index.vue 父組件
<template>
<div class="booking">
<!-- 導航欄 -->
<van-sticky>
<NavBar :title="title" @on-back="handleBack"></NavBar>
</van-sticky>
<div class="report_table_container">
<!-- 檢索組件 -->
<Search :searchList="searchList" @on-search="handleSearch"/>
<!-- table組件 -->
<Table :total="page.total" :columns="columns" :dataSource="dataSource" :tableType="tableType" @onRefresh="handleRefresh" :refreshLoading="refreshLoading" @onTableScroll="handleTableScroll">
<!--插槽部分-->
<template #summary>
<div class="report_table_summary" style="width: 12%">總計</div>
<div class="report_table_summary" style="width: 44%">0臺</div>
<div class="report_table_summary" style="width: 22%">¥0</div>
<div class="report_table_summary" style="width: 22%">¥0</div>
</template>
</ReportTable>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import { useRouter } from "vue-router";
import Search from "./components/Search.vue";
import Table from "./components/Table.vue";
//
const tableType = ref(1);
const router = useRouter();
const searchList = ref([
{
placeholder: "請輸入姓名",
value: "username",
},
{
placeholder: "別名",
value: "nickname",
},
]);
// 列表下拉loading
const refreshLoading = ref(false);
// 表頭
const columns = ref([
{
lable: "編號",
prop: "id",
width: '12%',
},
{
lable: "姓名",
prop: "username",
width: '22%',
},
{
lable: "別名",
prop: "nickname",
width: '22%',
},
{
lable: "金額",
prop: "money",
width: '22%',
moneyType: true
},
{
lable: "余額",
prop: "balance",
width: '22%',
moneyType: true
},
]);
// table內(nèi)容
const dataSource = ref([])
// 分頁參數(shù)
const page = ref({
pageNum: 1,
pageRow: 20,
total: 0,
});
onMounted(() => {
// 獲取明細數(shù)據(jù)
getList()
})
// 檢索
const handleSearch = (formData) => {
getList(formData)
}
// 滾動加載
const handleTableScroll = () => {
page.value.pageNum++;
getList()
}
// 獲取table列表
const getList = (searchParams) => {
const params = {
...page.value, // 分頁數(shù)據(jù)
...searchParams // search組件參數(shù)
}
.............
}
// 下拉刷新
const handleRefresh = () => {
page.value.pageNum = 1
refreshLoading.value = true
// 請求數(shù)據(jù) ......
getList()
}
const handleBack = () => {
router.go(-1);
};
</script>t pa