标题:Vue.js实现多条件筛选、搜索、排序及分页的表格功能攻略
介绍
在Vue.js中实现一个具有多条件筛选、搜索、排序及分页功能的表格,是一个非常常见的需求。这种表格通常用于展示大量数据,让用户可以方便地查找并进行各种操作。在本篇攻略中,将介绍如何使用Vue.js实现这样一个表格功能。
步骤
步骤一 - 准备和设计数据结构
在实现这样一个表格功能之前,需要准备和设计数据结构。一个标准的表格最少需要以下三个部分的数据:表头、表行和操作栏。同时,为了实现筛选、搜索、排序及分页功能,还需要定义一个包含上述数据的状态数据对象,并在初始化的时候给它设置默认值。
示例代码:
data: {
columns: [], // 表头
rows: [], // 表行
operations: [], // 操作栏
filter: {
keyword: '', // 关键词筛选
sorts: [], // 排序
filterConditions: [], // 筛选条件
currentPage: 1, // 当前页数
pageSize: 10, // 每页显示数量
total: 0 // 总记录数
}
}
步骤二 - 实现筛选功能
在Vue.js中实现筛选功能的方法有很多种,但最常见的做法是使用computed属性或包含setter的watcher属性,以实现响应式更新。同时,由于筛选条件可以有多个,需要将每个筛选条件视为一个对象,以实现多条件筛选。
示例代码:
computed: {
filteredData() {
let filteredData = this.rows.slice();
if (this.filter.keyword) {
filteredData = filteredData.filter(row => {
for (let col of this.columns) {
if (row[col.field].toString().toLowerCase().indexOf(this.filter.keyword) > -1) {
return true;
}
}
return false;
});
}
if (this.filter.filterConditions.length) {
filteredData = filteredData.filter(row => {
for (let condition of this.filter.filterConditions) {
if (!condition.check(row[condition.field], condition.value)) {
return false;
}
}
return true;
});
}
return filteredData;
}
}
步骤三 - 实现搜索功能
为了实现搜索功能,只需要添加一个输入框,并使用v-model指令绑定到filter.keyword属性即可。同时,也可以监听input事件,当用户在输入框中输入时,执行筛选操作以实时更新表格。
示例代码:
<div>
<label>关键词:</label>
<input type="text" placeholder="请输入关键词" v-model="filter.keyword" @input="onFilterChange($event.target.value)">
</div>
步骤四 - 实现排序功能
在实现排序功能之前,需要先定义一个排序条件的对象,包含字段名和升序或降序的信息。当用户点击表格的表头中的某个列时,插件将该列的字段名和升序或降序的信息添加到排序数组中,并对数据进行重新排序返回新的结果。
示例代码:
methods: {
onSortChange(column) {
if (column.sortable) {
for (let sort of this.filter.sorts) {
if (sort.field === column.field) {
sort.direction = sort.direction === 'desc' ? 'asc' : 'desc';
return;
}
}
this.filter.sorts.push({
field: column.field,
direction: 'asc'
});
}
}
},
computed: {
sortedData() {
let sortedData = this.filteredData.slice();
if (this.filter.sorts.length) {
sortedData.sort((a, b) => {
for (let sort of this.filter.sorts) {
let valueA = a[sort.field];
let valueB = b[sort.field];
if (sort.direction === 'desc') {
[valueA, valueB] = [valueB, valueA];
}
if (valueA < valueB) {
return -1;
} else if (valueA > valueB) {
return 1;
}
}
return 0;
});
}
return sortedData;
}
}
步骤五 - 实现分页功能
实现分页功能可以使用Vue.js提供的组件,例如vue-pagination
或vuejs-paginate
等。这些组件都可以为表格提供分页功能,并允许您将所需的分页信息传递给父组件,以便对当前页数、每页显示数量和总记录数进行更改。
示例代码:
<paginate :page-count="Math.ceil(filter.total / filter.pageSize)" :current-page.sync="filter.currentPage" :page-size="filter.pageSize" @input="onPageChange"></paginate>
methods: {
onPageChange(page) {
this.filter.currentPage = page;
}
},
computed: {
pagedData() {
this.filter.total = this.filteredData.length;
const start = (this.filter.currentPage - 1) * this.filter.pageSize;
const end = start + this.filter.pageSize;
return this.sortedData.slice(start, end);
}
}
示例说明
示例一 - 使用element-ui
Vue.js已经成为构建SPA的首选框架之一,而Element UI是目前最受欢迎的基于Vue.js的组件库之一,两者的结合可以快速实现一个交互体验优良的、功能完整的表格。
示例代码:
<template>
<div>
<el-table :data="pagedData" :border="border" :stripe="stripe">
<el-table-column v-for="column in columns" :key="column.field" :prop="column.field" :label="column.title" :width="column.width" :sortable="column.sortable">
<template v-if="typeof(column.formatter) === 'function'" slot-scope="{ row }">
{{ column.formatter(row[column.field], row) }}
</template>
</el-table-column>
<el-table-column :label="'操作'" :width="operationsWidth">
<template slot-scope="{ row }">
<el-button v-for="operation in operations" :key="operation.text" :type="operation.type" size="small" @click="operation.handler(row)">{{ operation.text }}</el-button>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 20px;">
<label>关键词:</label>
<el-input placeholder="请输入关键词" v-model="filter.keyword" @onInput="onFilterChange($event.target.value)" clearable></el-input>
<el-button-group>
<el-dropdown>
<el-button type="primary" size="small">
排序
<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="column in columns" :key="column.field" v-if="column.sortable" @click="onSortChange(column)">
<i :class="{'el-icon-arrow-up': sort.direction === 'asc', 'el-icon-arrow-down': sort.direction === 'desc', 'el-icon-sort': sort.field !== column.field }" style="margin-right: 5px;"></i>
{{ column.title }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-pagination layout="total, sizes, prev, pager, next, jumper" :total="filter.total" :page-sizes="[10, 20, 50, 100]" :page-size="filter.pageSize" :current-page.sync="filter.currentPage" @size-change="onPageSizeChange" @current-change="onPageChange"></el-pagination>
</el-button-group>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
data() {
return {
border: false,
stripe: true,
operationsWidth: 100,
};
},
computed: {
...mapState(['columns', 'rows', 'operations', 'filter']),
sort: {
get() {
return this.filter.sorts.length ? this.filter.sorts[0] : {};
},
set(value) {
this.filter.sorts = [value];
this.$forceUpdate();
}
}
},
methods: {
onPageChange(page) {
this.filter.currentPage = page;
},
onPageSizeChange(size) {
this.filter.pageSize = size;
this.filter.currentPage = 1;
},
onFilterChange(value) {
this.filter.keyword = value.trim().toLowerCase();
},
onSortChange(column) {
if (column.sortable) {
const index = this.filter.sorts.findIndex(sort => sort.field === column.field);
const sort = {
field: column.field,
direction: 'asc'
};
if (index > -1) {
const direction = this.filter.sorts[index].direction;
sort.direction = direction === 'asc' ? 'desc' : 'asc';
}
this.sort = sort;
}
}
}
};
</script>
示例二 - 使用vuetable-2
vuetable-2
是一个轻量级的、全功能的、可重用的Vue.js表格组件。该组件可以快速地将数据渲染为HTML表格,并提供多种特性,如排序、筛选和分页等。
示例代码:
<template>
<div>
<vuetable ref="vuetable" :fields="columns" :table-class="'table table-striped table-bordered table-hover'" :data="pagedData" :no-data-template="'未找到符合要求的数据!'" :pagination-path="'filter'" @vuetable:pagination-data="onPaginationData">
<template slot="action" slot-scope="props">
<div class="btn-group">
<button type="button" class="btn btn-info btn-sm" :disabled="!props.row.id || props.row.isDeleted" @click="onEdit(props.row)">编辑</button>
<button type="button" class="btn btn-danger btn-sm" :disabled="!props.row.id || props.row.isDeleted" @click="onDelete(props.row)">删除</button>
</div>
</template>
<template slot="filter__name" slot-scope="props">
<input class="form-control" type="text" :value.sync="props.filterValue" @input="props.updateValue($event.target.value)">
</template>
</vuetable>
<div class="row" v-show="filter.total > filter.pageSize">
<div class="col-sm-6">
<div class="dataTables_info" role="status" aria-live="polite">显示{{ (filter.currentPage - 1) * filter.pageSize + 1 }}到{{ Math.min(filter.currentPage * filter.pageSize, filter.total) }}个 总{{ filter.total }}个数据</div>
</div>
<div class="col-sm-6">
<div class="dataTables_paginate text-right">
<vue-pagination :pagination.sync="filter" :css-classes="pageClass"></vue-pagination>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import Vuetable from 'vuetable-2';
import VuetablePagination from 'vuetable-2/src/components/VuetablePagination.vue';
import VuePagination from 'vue-pagination-2';
Vue.component('vuetable', Vuetable);
Vue.component('vuetable-pagination', VuetablePagination);
Vue.component('vue-pagination', VuePagination);
export default {
data() {
return {
pageClass: {
wrapper: 'pagination',
activeClass: 'page-item active',
disabledClass: 'disabled',
pageClass: 'page-item',
linkClass: 'page-link'
}
}
},
computed: {
columns() {
return [
{ name: 'name', title: '名称', sortable: true },
{ name: 'username', title: '用户名', sortable: true },
{ name: 'email', title: '邮箱地址', sortable: true },
{ name: 'age', title: '年龄', sortable: true },
{ name: 'gender', title: '性别', formatter: value => value === 'MALE' ? '男' : '女' },
{ name: '__slot:action', title: '操作', width: '120px', sortable: false }
]
},
pagedData() {
return this.$refs.vuetable && this.$refs.vuetable.localPagination.total > 0 ? this.$refs.vuetable.tableData.slice((this.$refs.vuetable.localPagination.currentPage - 1) * this.filter.pageSize, this.$refs.vuetable.localPagination.currentPage * this.filter.pageSize) : [];
}
},
methods: {
onPaginationData(pagination) {
this.filter.currentPage = pagination.currentPage;
this.filter.pageSize = pagination.perPage;
this.filter.total = pagination.total;
},
onEdit(row) {
// TODO: 编辑操作
},
onDelete(row) {
// TODO: 删除操作
}
}
};
</script>
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue.js实现多条件筛选、搜索、排序及分页的表格功能 - Python技术站