table组件示例
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>
<!-- 内容区域 -->
<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>
<!-- 暂无内容区域 -->
<div class="no_data" v-else>
<span class="data_text">暂无内容</span>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const props = defineProps({
// 当前加载的table类型, 1. 滚动动态请求数据 2. 滚动不请求数据
tableType: {
type: Number,
default: null,
},
// 列表数据
dataSource: {
type: Array,
default: () => [],
},
// 列表字段
columns: {
type: Array,
default: () => [], // width 参数建议设置 百分比,设置百分比可自适应
},
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是滚动条可视区域的高度
const clientHeight =
tableRef.value.clientHeight;
// 当滚动条到达底部,并且距离底部小于10px时,加载数据
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内容
const dataSource = ref([])
// 分页参数
const page = ref({
pageNum: 1,
pageRow: 20,
total: 0,
});
onMounted(() => {
// 获取明细数据
getList()
})
// 检索
const handleSearch = (formData) => {
getList(formData)
}
// 滚动加载
const handleTableScroll = () => {
page.value.pageNum++;
getList()
}
// 获取table列表
const getList = (searchParams) => {
const params = {
...page.value, // 分页数据
...searchParams // search组件参数
}
.............
}
// 下拉刷新
const handleRefresh = () => {
page.value.pageNum = 1
refreshLoading.value = true
// 请求数据 ......
getList()
}
const handleBack = () => {
router.go(-1);
};
</script>t pa