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>
阅读剩余 85%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue.js实现多条件筛选、搜索、排序及分页的表格功能 - Python技术站

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

相关文章

  • vuejs element table 表格添加行,修改,单独删除行,批量删除行操作

    以下是“vuejs element table 表格添加行,修改,单独删除行,批量删除行操作”的攻略。 添加行 要添加行,首先需要在data中定义一个空的数组来存放表格数据。然后,在模板中使用el-table组件和el-table-column组件来渲染表格,并给el-table组件绑定数据源。 接下来,我们可以在模板中添加一个类似“添加行”的按钮,当用户点…

    Vue 2023年5月28日
    00
  • Vue中fragment.js使用方法详解

    Vue中fragment.js使用方法详解 在前端开发中,我们经常需要在一个组件内部返回多个连续节点,并将它们包装在一个 DOM 元素中。在 Vue 中,我们可以使用 Fragment 实现这一操作。但是在 Vue 2.x 中,Fragment API 并没有提供支持,为了解决这个问题,我们可以使用 fragment.js 这个第三方库来帮助我们使用 Fra…

    Vue 2023年5月27日
    00
  • 关于Vue3中defineProps用法图文详解

    什么是 defineProps?defineProps 是 Vue3 中一种新的组件数据传递方式,可以用于在子组件中定义接收哪些父组件的 props。当父组件的 props 发生变化时,子组件也会随之响应。 如何使用 defineProps?在子组件中可以使用 defineProps 声明该组件需要接收的 props,它需要传递一个包含 props 字段的对…

    Vue 2023年5月28日
    00
  • Vue 自定义指令实现一键 Copy功能

    Vue 自定义指令实现一键 Copy 功能 简介 Vue 自定义指令可以让我们扩展 Vue 模板语法。在这篇文章中,我们会讲解如何使用自定义指令实现一键 Copy 功能。 步骤 创建一个自定义指令 javascript Vue.directive(‘copy’, { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el)…

    Vue 2023年5月27日
    00
  • 在vue中使用eslint,配合vscode的操作

    确保已安装Vue CLI和VS Code,并在Vue项目中启用ESLint扩展。 步骤一:安装ESLint 在终端中运行以下命令安装ESLint: npm install eslint -D 步骤二:安装Vue ESLint插件 运行以下命令安装Vue ESLint插件: npm install eslint-plugin-vue -D 步骤三:初始化一个E…

    Vue 2023年5月28日
    00
  • vue路由传参的基本实现方式小结【三种方式】

    下面是详细的“vue路由传参的基本实现方式小结【三种方式】”攻略: 一、query方式 在router-link中添加to属性,例如: <router-link :to="{path: ‘detail’, query: {id: 1, name: ‘foo’}}"> 去往详情 </router-link> 这里在t…

    Vue 2023年5月27日
    00
  • vue+axios实现post文件下载

    下面是 vue+axios 实现 post 文件下载的攻略: 1. 前置条件 在进行 post 文件下载的功能实现之前,需要确保你已经安装了以下依赖: Vue.js:用于前端开发 axios:用于网络请求 file-saver:用于文件下载 如果还没有安装,可以使用以下命令进行安装: npm install vue axios file-saver –sa…

    Vue 2023年5月28日
    00
  • vue封装一个图案手势锁组件

    下面是关于如何封装一个Vue图案手势锁组件的攻略: 1. 设计组件结构 首先,我们需要想一想组件的结构和功能。一般来说,手势锁的作用是让用户通过手指在一个类似九宫格的区域内绘制一条路径,然后判断这条路径是否符合某个预定的模式。因此,我们可以考虑将组件拆分为以下几个部分: 1.1 手势绘制区域 这是手势锁的主要区域,用户可以在这里通过手指绘制手势路径。我们可以…

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