组件文档
表格分页组件
参数
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
total | Number | 0 | 总条数 |
page | Number | 1 | 初始化加载页数 |
limit | Number | 20 | 每页的记录行数 |
pageSizes | Array | [10, 20, 30, 50] | 可供选择的每页的行数 |
pagerCount | Number | 5 | 设置最大页码按钮数 |
layout | String | total, sizes, prev, pager, next, jumper | 组件布局,子组件名用逗号分隔 |
background | Boolean | true | 是否为分页按钮添加背景色 |
autoScroll | Boolean | true | 自动滚动到顶部 |
hidden | Boolean | false | 是否显示分页 |
pagination | 事件 | 函数 | 分页事件 |
案例
html
<template>
<div>
<pagination
:total="total"
v-model:page="currentPage"
v-model:limit="limit"
v-model:pageSizes="pageSizes"
:layout="pagelayout"
:background="backgroundpage"
:autoScroll="autoScrollpage"
:hidden="hiddenpage"
@pagination="changePage"
>
</pagination>
</div>
</template>
<script setup>
const { proxy } = getCurrentInstance();
const total = ref(567);
const currentPage = ref(1);
const limit = ref(20);
const pageSizes = ref([10, 20, 30, 40, 50]);
const pagelayout = ref("total, sizes, prev, pager, next");
const backgroundpage = ref(true);
const autoScrollpage = ref(true);
const hiddenpage = ref(false);
const changePage = () => {
console.log("当前页码", currentPage.value);
console.log("每页条数", limit.value);
// 执行分页逻辑
// 例如:获取数据、更新状态等
};
</script>
<style lang="scss" scoped></style>
表格组件
安装横向滚动条
- 这里就是当表格高度过高的时候.底部有个滚动条方便滑动
js
npm i el-table-horizontal-scroll -S
- main.js
js
// 表格固定底部的滚动条
import horizontalScroll from "el-table-horizontal-scroll";
app.use(horizontalScroll);
封装 table 表格组件
components/MyTable.vue
注意
- 使用的时候修改 getList,依据后台的包来修改字段
html
<template>
<el-card class="my-table-card">
<div v-if="title !== ''" slot="header" class="my-table-header">
<span v-if="totalFlag" class="title">共计{{ total }}条</span>
<span class="title">{{ title }}</span>
<span class="btn-box">
<slot name="btn"></slot>
</span>
</div>
<el-table
v-loading="tableLoading"
:data="tableList"
:highlight-current-row="true"
tooltip-effect="dark"
border
style="width: 100%"
@selection-change="selectionChange"
@sort-change="sortChange"
v-horizontal-scroll="'always'"
>
<el-table-column
v-if="isSelection"
type="selection"
align="center"
width="50"
></el-table-column>
<slot></slot>
</el-table>
<el-pagination
v-if="hasPagination"
background
class="my-table-pagination"
:current-page="currPage"
:page-sizes="pageSizes"
:page-size="limit"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
</el-card>
</template>
<script setup>
import { ElMessage } from "element-plus";
const route = useRoute();
const emit = defineEmits(["data"]);
const props = defineProps({
title: {
type: String,
default: "",
},
api: {
type: Function,
required: true,
},
search: {
type: Object,
default: () => {
return {};
},
},
isSelection: {
type: Boolean,
default: false,
},
pageRecordName: {
type: String,
default: "",
},
totalFlag: {
type: Boolean,
default: false,
},
hasPagination: {
type: Boolean,
default: true,
},
fixedTableHeader: {
type: Boolean,
default: true,
},
pageSizes: {
type: Array,
default: () => {
return [10, 20, 50, 100];
},
},
});
const scroll = ref(0);
const mySearch = ref(props.search);
const multipleSelection = ref([]);
const tableList = ref([]);
const tableLoading = ref(false);
const total = ref(0);
const currPage = ref(1);
const totalPage = ref(1);
const limit = ref(20);
const myPageRecordName = ref(
props.pageRecordName ? props.pageRecordName : route.fullPath
);
const order_field = ref("");
const order_sort = ref("");
const handleScroll = () => {
scroll.value =
document.documentElement.scrollTop || document.body.scrollTop; // 滚动条距顶部距离
const containerEleTable = document.querySelector(`.el-table`); // el-table元素
const containerEleHeader = document.querySelector(
`.el-table .el-table__header-wrapper`
); // el-table元素的子元素el-table__header
const containerEleHeaderLeftFixed = document.querySelector(
`.el-table .el-table__fixed .el-table__fixed-header-wrapper`
); // el-table有左边fixed的table元素的子元素el-table__header
const containerEleHeaderRightFixed = document.querySelector(
`.el-table .el-table__fixed-right .el-table__fixed-header-wrapper`
); // el-table有右边fixed的table元素的子元素el-table__header
const containerEleBody = document.querySelector(
`.el-table .el-table__body-wrapper`
); // el-table元素的子元素el-table__body
const containerEleHeaderTh = document.querySelectorAll(
`.el-table thead tr th `
);
const offsetTop = containerEleTable.offsetTop - 50; // 头部固定条高度
const table_w = window.getComputedStyle(containerEleTable).width;
const height = window.getComputedStyle(containerEleHeader).height; // el-table元素的子元素el-table__header高度
if (scroll.value > offsetTop) {
// el-table元素的子元素el-table__header距顶部50个单位时
containerEleHeader.classList.add("table-header-fixed"); // el-table元素的子元素el-table__header添加样式class类名 table-header-fixed
containerEleBody.style.marginTop = height; // el-table元素的子元素el-table__body添加距marginTop,否则会有抖动
containerEleHeader.style.width = table_w; // 控制el-table__header-wrapper宽度,解决el-table__header-wrapper超出table
if (containerEleHeaderLeftFixed) {
containerEleHeaderLeftFixed.classList.add("table-header-fixed");
containerEleHeaderLeftFixed.style.width = table_w;
}
if (containerEleHeaderRightFixed) {
containerEleHeaderRightFixed.classList.add("table-header-right-fixed");
}
} else {
containerEleHeader.classList.remove("table-header-fixed");
if (containerEleHeaderLeftFixed) {
containerEleHeaderLeftFixed.classList.remove("table-header-fixed");
}
if (containerEleHeaderRightFixed) {
containerEleHeaderRightFixed.classList.remove(
"table-header-right-fixed"
);
}
containerEleBody.style.marginTop = 0;
}
containerEleHeaderTh.forEach((ele) => {
// 找到el-table__header-wrapper下边的th有is-hidden类名的删除is-hidden类名
if (ele.classList.contains("is-hidden")) {
ele.classList.add("is-hidden-z");
}
});
};
// 初始化
const init = (reset = true) => {
if (reset) {
currPage.value = 1;
}
getList();
};
// 获取数据
const getList = () => {
tableLoading.value = true;
const data = mySearch.value;
data.page = currPage.value;
data.size = limit.value;
if (order_field.value != "") {
data.order_field = order_field.value;
}
if (order_sort.value != "") {
data.order_sort = order_sort.value;
}
props
.api(data)
.then((res) => {
console.log(res);
if (res.code === 200) {
if (props.hasPagination) {
// 有分页
if (typeof res.total !== "undefined") {
totalPage.value = Math.ceil(res.total / limit.value);
total.value = res.total;
tableList.value = [];
tableList.value = tableList.value.concat(res.list);
} else {
if (typeof res.total !== "undefined") {
totalPage.value = Math.ceil(res.total / limit.value);
total.value = res.total;
tableList.value = [];
let result = res.list || res.data.data;
tableList.value = tableList.value.concat(result);
} else {
currPage.value = res.curentpage;
totalPage.value = res.page;
total.value = res.total;
tableList.value = res.list;
}
}
} else {
if (res.list) {
tableList.value = res.list;
} else {
tableList.value = res.data;
}
}
emit("data", res.data);
} else {
ElMessage.warning(res.msg);
}
tableLoading.value = false;
})
.catch(() => {
// ElMessage.warning('请求失败了');
// tableLoading.value = false;
});
};
const savePage = () => {
if (!myPageRecordName.value) {
return false;
}
window.sessionStorage.setItem(
myPageRecordName.value,
JSON.stringify({ page: currPage.value, size: limit.value })
);
};
const getPageRecord = () => {
let data = window.sessionStorage.getItem(myPageRecordName.value);
if (!data || typeof data === "undefined" || data === "null") {
return false;
}
data = JSON.parse(data);
currPage.value = data.page;
limit.value = data.size;
};
const handleCurrentChange = (page) => {
currPage.value = page;
getList();
savePage();
};
const handleSizeChange = (size) => {
currPage.value = 1;
limit.value = size;
getList();
savePage();
};
const selectionChange = (val) => {
multipleSelection.value = val;
};
const getSelection = () => {
return multipleSelection.value;
};
const getTableDate = () => {
const tableDate = Object.assign({
tableList: tableList.value,
limit: limit.value,
currPage: currPage.value,
});
return tableDate;
};
const sortChange = (column) => {
order_field.value = column.prop;
order_sort.value = column.order.replace("ending", "");
getList();
};
watch(
() => {
return props.search;
},
(val) => {
mySearch.value = val;
}
);
onMounted(() => {
// 设置分页
getPageRecord();
init(false); // 初始化
if (props.fixedTableHeader) {
window.addEventListener("scroll", handleScroll);
}
});
onUnmounted(() => {
window.removeEventListener("scroll", handleScroll);
});
defineExpose({
init,
getSelection,
getTableDate,
});
</script>
<style lang="scss" scoped>
.my-table-card {
:deep(.el-card__header) {
padding: 10px 20px;
}
.my-table-header {
display: flex;
justify-content: space-between;
.title {
font-size: 12px;
font-weight: bold;
line-height: 32px;
}
}
:deep(.el-table__header thead tr th) {
background: #f9f9f9;
}
:deep(.el-table--small .el-table__body td) {
padding: 5px 0;
}
.my-table-pagination {
margin-top: 10px;
}
}
.my-table-card {
:deep(.el-table) {
.table-header-fixed {
position: fixed;
top: 50px;
left: auto;
z-index: 100;
border-top: 1px solid #dfe6ec;
}
.table-header-right-fixed {
position: fixed;
top: 50px;
right: 46px;
z-index: 200;
border-top: 1px solid #dfe6ec;
}
.el-table__header {
thead {
tr {
background: rgba(0, 0, 0, 0);
}
}
}
}
}
:deep(.is-hidden-z) {
opacity: 0;
// top: -50px;
}
:deep(.el-scrollbar__bar) {
&.is-horizontal {
height: 16px !important;
background: #dfe6ec !important;
}
}
</style>
使用
vue
<template>
<div class="useManagePage">
<LineTitle :title="$t('message.route.userManage')">
<el-button
type="primary"
@click="getselectdata"
style="padding-left: 20px; padding-right: 20px"
>获取选中数据</el-button
>
</LineTitle>
<MyTable
:api="getUserManageList"
:search="searchdata"
ref="userManageRef"
isSelection="true"
>
<el-table-column prop="id" label="id" width="180" align="center" />
<el-table-column
prop="username"
label="昵称"
width="180"
align="center"
/>
<el-table-column prop="avatar" label="头像" width="180" align="center">
<template #default="{ row }">
<img
:src="row.avatar"
alt=""
style="width: 50px; height: 50px; border-radius: 50%"
/>
</template>
</el-table-column>
<el-table-column prop="openTime" label="创建时间" align="center">
<template #default="{ row }">
{{ getTime(row.openTime) }}
</template>
</el-table-column>
<el-table-column prop="mobile" label="手机号" align="center" />
<el-table-column prop="role" label="权限" align="center">
<template #default="{ row }">
<span v-for="(content, index) in row.role" :key="index">
{{ content.title }}
</span>
</template>
</el-table-column>
</MyTable>
</div>
</template>
<script setup>
import { getUserManageList } from "@/api/admin/userManager";
import { ElMessage } from "element-plus";
const searchdata = ref({});
const getTime = (timestamp) => {
const date = new Date(parseInt(timestamp)); // 创建 Date 对象
const year = date.getFullYear(); // 获取年份
const month = date.getMonth() + 1; // 获取月份(注意月份从 0 开始,需要加 1)
const day = date.getDate(); // 获取日期
// 格式化为 YYYY-MM-DD
const formattedDate = `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")}`;
return formattedDate;
};
const userManageRef = ref(null);
const getselectdata = () => {
console.log(userManageRef.value.getSelection());
let result = [];
userManageRef.value.getSelection().forEach((item) => {
result.push(item.id);
});
let str = result.join(",");
ElMessage({
message: `选中了id是${str}数据`,
type: "success",
});
};
</script>
<style lang="scss" scoped>
.useManagePage {
padding-top: 30px;
padding-left: 15px;
padding-right: 15px;
}
</style>