Vue.js 中使用 Element UI 实现异步加载分页列表
在前端开发中,我们常常需要展示大量数据,并提供分页浏览的功能。本篇博客将介绍如何使用 Vue.js 和 Element UI 组件库创建一个简单的异步加载分页列表。
技术栈
- Vue.js
- Element UI
- JavaScript
组件结构
我们将创建一个包含表格和分页组件的 Vue 单文件组件。以下是组件的基本结构:
<template>
<div class="table-container">
<!-- 表格组件 -->
<el-table :data="currentPageData" style="width: 66%">
<el-table-column label="ID" prop="id"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="价格" prop="price"></el-table-column>
</el-table>
<!-- 分页组件 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="tableData.length"
></el-pagination>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [], // 存储列表数据
currentPage: 1, // 当前页码
pageSize: 10, // 每页条数
};
},
computed: {
currentPageData() {
// 根据当前页码和每页条数计算当前显示数据
const start = (this.currentPage - 1) * this.pageSize;
const end = start + this.pageSize;
return this.tableData.slice(start, end);
},
},
methods: {
handleSizeChange(val) {
// 处理每页条数变化
this.pageSize = val;
this.currentPage = 1; // 将当前页重置为第一页
},
handleCurrentChange(val) {
// 处理当前页变化
this.currentPage = val;
},
},
created() {
// 模拟异步加载数据
setTimeout(() => {
this.tableData = Array.from({ length: 33 }, (_, index) => ({
id: index + 1,
name: `商品${index + 1}`,
price: Math.floor(Math.random() * 100) + 50,
}));
}, 500);
},
};
</script>
<style scoped>
.table-container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
</style>
创建过程
-
引入 Element UI: 在项目中引入 Element UI 组件库。可以使用 npm 或 yarn 安装 Element UI。
npm install element-ui
在
main.js
中引入并使用 Element UI:import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
-
创建组件: 创建一个 Vue 单文件组件,定义表格和分页的结构。
-
异步加载数据: 使用
created
钩子模拟异步加载数据。在实际项目中,将从后端 API 获取数据。 -
分页功能: 使用 Element UI 提供的分页组件实现分页功能。监听分页组件的事件,更新当前页码和每页条数。
main.js :
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import ListDisplay from './components/ListDisplay.vue';
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
render: h => h(App),
components: {
ListDisplay,
},
template: '<ListDisplay />',
}).$mount('#app')
App.vue:
<template>
<div id="app">
<ListDisplay />
</div>
</template>
<script>
import ListDisplay from "@/components/ListDisplay.vue";
// import ListDisplay from "@/components/separation-of-duties/ListDisplay.vue";
export default {
name: 'App',
components: {
ListDisplay,
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
当然列表组件也可以拆开来展示
<template>
<div class="table-container">
<MyTable :data="currentPageData"></MyTable>
<MyPagination
:current-page="currentPage"
:page-size="pageSize"
:total="tableData.length"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></MyPagination>
</div>
</template>
<script>
import MyTable from "././MyTable.vue";
import MyPagination from "././MyPagination.vue";
export default {
components: {
MyTable,
MyPagination,
},
data() {
return {
tableData: [],
currentPage: 1,
pageSize: 10,
};
},
computed: {
currentPageData() {
const start = (this.currentPage - 1) * this.pageSize;
const end = start + this.pageSize;
return this.tableData.slice(start, end);
},
},
methods: {
handleSizeChange(val) {
this.pageSize = val;
this.currentPage = 1;
},
handleCurrentChange(val) {
this.currentPage = val;
},
},
created() {
// 模拟异步加载数据
setTimeout(() => {
this.tableData = Array.from({length: 33}, (_, index) => ({
id: index + 1,
name: `商品${index + 1}`,
price: Math.floor(Math.random() * 100) + 50,
}));
}, 500);
},
};
</script>
<style scoped>
.table-container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
</style>
MyTable:
<template>
<el-table :data="data" style="width: 100%">
<el-table-column label="ID" prop="id"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="价格" prop="price"></el-table-column>
</el-table>
</template>
<script>
export default {
props: {
data: {
type: Array,
default: () => [],
},
},
};
</script>
<style scoped>
</style>
MyPagination:
<template>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-size="pageSize"
:page-sizes="[10, 20, 30, 40]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</template>
<script>
export default {
props: {
currentPage: {
type: Number,
required: true,
},
pageSize: {
type: Number,
required: true,
},
total: {
type: Number,
required: true,
},
},
methods: {
handleSizeChange(val) {
this.$emit('size-change', val);
},
handleCurrentChange(val) {
this.$emit('current-change', val);
},
},
};
</script>
<style scoped>
</style>
实现效果: