Vue.js实现多条件筛选、搜索、排序及分页的表格功能

标题: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-paginationvuejs-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) }}个&nbsp;&nbsp;总{{ 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技术站

(0)
上一篇 2023年5月29日
下一篇 2023年5月29日

相关文章

  • 利用vuex-persistedstate将vuex本地存储实现

    利用 vuex-persistedstate 可以将 Vuex 状态持久化到本地存储中,目的是为了在页面刷新后还能够保持之前的状态。下面是 vuex-persistedstate 的完整攻略: 安装 在项目目录下执行以下命令安装 vuex-persistedstate: npm install vuex-persistedstate –save 引入 在您…

    Vue 2023年5月27日
    00
  • vue2.0 与 bootstrap datetimepicker的结合使用实例

    下面我将详细讲解“vue2.0 与 bootstrap datetimepicker的结合使用实例”的完整攻略。 什么是bootstrap datetimepicker? bootstrap datetimepicker是基于Bootstrap样式的日期和时间选择插件。它可以方便地自定义日期和时间格式,支持语言环境等功能,非常适合用于日期和时间的选择和显示。…

    Vue 2023年5月29日
    00
  • 简单了解vue 插值表达式Mustache

    下面是“简单了解vue 插值表达式Mustache”的完整攻略。 插值表达式Mustache 在Vue.js中,使用Mustache语法(双大括号,即{{}})可以用于实现对数据的简单渲染,这种方式被称为插值表达式Mustache。在Vue实例中使用Mustache语法可以对绑定到数据的值进行渲染,即实现数据与视图的绑定。 基本使用 使用插值表达式Musta…

    Vue 2023年5月27日
    00
  • Vue使用canvas实现图片压缩上传

    下面是如何使用Vue和Canvas实现图片压缩上传的完整攻略: 1. 安装Canvas库 首先,为了使用Canvas,我们需要安装Canvas库。在Vue项目的目录下,打开终端并运行以下命令: npm install canvas vue-canvas 2. 创建Canvas组件 接下来我们需要在Vue中创建一个自定义的Canvas组件。在组件中,我们将实现…

    Vue 2023年5月28日
    00
  • vue webpack打包优化操作技巧

    下面是关于Vue Webpack打包优化的完整攻略。 为什么需要打包优化? Vue Webpack打包过程通常比较复杂,对于大型项目而言,打包过程中可能会遇到各种各样的问题。我们需要对Webpack打包进行优化,以提高项目的性能和稳定性。通常需要考虑以下几个方面: 减少打包体积 减少打包时间 提高页面加载速度 稳定可靠性 打包优化操作技巧 1. 优化load…

    Vue 2023年5月28日
    00
  • Vue 前端导出后端返回的excel文件方式

    Vue 前端导出后端返回的 Excel 文件是一个常见的需求,以下是一种完整的实现攻略。 确认后端返回的 Excel 文件格式 在实现 Vue 前端导出后端返回的 Excel 文件之前,我们需要先确认后端返回 Excel 文件的格式。通常情况下,我们可以使用两种方式来返回 Excel 文件: 1. 直接返回二进制流 后端直接将 Excel 文件的二进制流作为…

    Vue 2023年5月27日
    00
  • 详谈Object.defineProperty 及实现数据双向绑定

    详谈Object.defineProperty 及实现数据双向绑定 Object.defineProperty 在 JavaScript 中,可以使用 Object.defineProperty() 方法来定义或修改一个对象的属性。该方法可以为一个对象的指定属性设置各种特性,包括值、可枚举性、可配置性和可写性等。 该方法的语法如下: Object.defin…

    Vue 2023年5月27日
    00
  • vue+element开发使用el-select不能回显的处理方案

    下面是详细的解释。 背景 在Vue+Element前端开发中,使用el-select组件时,有时我们需要实现对下拉选项的回显功能。但是实际使用中,发现el-select在使用v-model绑定数据进行回显时存在问题,即无法正确地显示默认值。 原因 这是因为在Vue中,父组件在挂载之前会先于子组件执行,导致el-select还没有加载完,所以无法正确地设置默认…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部