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

yizhihongxing

标题: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日

相关文章

  • Vue.js 2.5新特性介绍(推荐)

    Vue.js 2.5新特性介绍(推荐) Vue.js 2.5是Vue.js的一个重要版本,在它被发布后,带来了很多有用的新特性和重要的改进,使得Vue.js更加易用且强大。在本文中,我们将会介绍Vue.js 2.5中的主要新特性,并且提供一些例子来说明它们的用法。 渐进式渲染(SSR) Vue.js 2.5是一个完全支持服务器端渲染的版本。服务器端渲染(SS…

    Vue 2023年5月27日
    00
  • 如何使用 Vuex的入门教程

    下面我将给出“如何使用 Vuex的入门教程”的详细攻略: 1. Vuex是什么 Vuex是一个专为Vue.js应用程序开发的状态管理模式(store)+库,它采用集中式存储管理应用的所有组件状态,并以相应的规则保证状态以一种可预测的方式发生变化。 2. 如何安装并使用Vuex (1)在Vue项目中安装Vuex: 在项目目录下打开终端,执行以下命令: npm …

    Vue 2023年5月27日
    00
  • 在vue中封装方法以及多处引用该方法详解

    在Vue中,我们可以通过封装方法来复用代码,提高开发效率。下面我将详细介绍如何在Vue中封装方法以及多处引用该方法的实现方法。 封装方法 在Vue中封装方法可以通过创建一个公共JS文件来实现。假设我们需要封装一个计算年龄的方法。 创建utils.js文件 您可以在项目的src目录下创建一个名为utils.js的文件。 定义计算年龄方法 在utils.js中定…

    Vue 2023年5月27日
    00
  • 详解给Vue2路由导航钩子和axios拦截器做个封装

    让我们来详细讲解“详解给Vue2路由导航钩子和axios拦截器做个封装”的攻略。 1. Vue2路由导航钩子封装 路由导航钩子是Vue Router 提供的一种非常有用的功能,它允许我们在路由跳转时执行一些额外的逻辑,例如验证用户是否登录、切换页面时的动画效果等。我们可以使用全局导航钩子或者单独路由的导航钩子。这里我们介绍一下全局导航钩子的封装: impor…

    Vue 2023年5月28日
    00
  • 详解如何使用webpack打包Vue工程

    下面我将为您详细讲解如何使用Webpack打包Vue工程: 环境准备 在使用Webpack打包Vue工程前,我们需要先搭建一些必要的环境: 安装Node.js和npm:Webpack依赖于Node.js和npm,需要先安装Node.js,并将npm更新至最新版本; 全局安装Webpack和Webpack-cli:输入命令npm install -g webp…

    Vue 2023年5月28日
    00
  • Vue render渲染时间戳转时间,时间转时间戳及渲染进度条效果

    下面我将为您详细讲解“Vue render渲染时间戳转时间,时间转时间戳及渲染进度条效果”的完整攻略。 Vue render渲染时间戳转时间 在Vue的render功能中,我们经常需要将服务器端返回的时间戳转换成我们常用的时间格式。这里向大家推荐moment.js这个库,它是一个轻量级的JavaScript日期库,可以帮助我们方便地转换时间格式。下面是一个简…

    Vue 2023年5月29日
    00
  • Vue中的生命周期介绍

    下面是关于Vue中的生命周期介绍的完整攻略及示例: 什么是Vue的生命周期 Vue生命周期是指Vue组件从创建到销毁的整个过程中,它所要经历的各个阶段。Vue生命周期分为8个不同的阶段,每个阶段都有相应的钩子函数,可以在相应的时候进行自定义操作。 Vue生命周期的8个钩子函数 下面是Vue生命周期的8个钩子函数,从创建到销毁依次为: beforeCreate…

    Vue 2023年5月29日
    00
  • axios接口管理优化操作详解

    当我们开发使用Axios进行接口请求时,随着业务需求的增多,接口请求的数量不断增加,对于接口的管理和维护也变得愈加重要。 因此,我们需要一套有效的接口管理优化操作方案,以方便项目的开发和维护。本篇文章将带你深入了解这方面的知识,包括以下内容: 一、接口统一管理 接口的统一管理是项目开发过程中非常重要的一环。通过接口管理模块,可以方便地调用后端提供的接口,减少…

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