Skip to content

vxe-table 前端控制数据渲染(筛选 + 排序+ 分页)(2)

场景需求

  • 场景需求,调用后端接口每次查询的数据,要累加到前端做存储,做统一控制
  • 实现功能:前端分页查看,搜索筛选,排序

前置

实现思路

外层触发计算

  • 列表数据增加

    js
    allData: {
      type: Array, default: () => []
    },

内层触发计算

  • 1、过滤filter

    js
    fileterData () {
      let data = []
    
      data =
        this.filterList.length > 0
          ? this.filterList.reduce((pre, next) => {
            // 筛选是且关系,reduce逐层过滤
            // 过滤列表,依次对数据进行过滤
            // pre 做为过滤之后的数据返回
            // next 做为每一次的过滤条件
            return pre.filter((item) =>
              // item[next.field] 是当前行的数据
              // next.datas[0] 是第一条过滤条件
              filterValue(item[next.field], next.datas ? next.datas[0] : next)
            )
          }, this.allData)
          : this.allData
    
      return data
    },
    • 过滤数据分三大类型:字符串、数字、日期(时间)
    js
    export function filterValue(n, filterData) {
      switch (filterData.valueType) {
        case 'string': {
          return filterStringValue(n, filterData)
        }
        case 'number': {
          return filterNumberValue(n, filterData)
        }
        case 'date':
        case 'time':
        case 'datetime': {
          return filterDateValue(n, filterData, filterData.valueType)
        }
        default:
      }
    
      return false
    }
    • 以字符串为例,根据不同的过滤条件,进行不同的数据过滤
    js
    export function filterStringValue(n, filterData) {
      switch (filterData.condition) {
        case 'eq': {
          // return (!isEmpty(n) && filterData.values?.some((item) => String(item) === String(n))) ?? false
    
          return (!isEmpty(n) && String(filterData.value) === String(n)) ?? false
        }
        case 'include': {
          return !isEmpty(n) && String(n).includes(String(filterData.value))
        }
        case 'isEmpty': {
          return isEmpty(n)
        }
        case 'isNotEmpty': {
          return !isEmpty(n)
        }
        case 'in': {
          return !isEmpty(n) && filterData.values.includes(String(n))
        }
        default:
      }
    
      return false
    }
  • 2、排序sort

    js
    sortData () {
      const data = this.fileterData
    
      if (this.sortList.length > 0) {
        data.sort((a, b) => {
          // 排序条件多条:依次对排序列表进行过滤
          // 比如有两个字段,一个正序,一个倒序
          // 先以第一个排序条件优先,!==0则大小已定,===0对应数值相同,则进行下一个排序条件,进行排序
          // 参考后端排序算法
          for (const list of this.sortList) {
            const res = sortValue(a, b, list)
    
            if (res !== 0) {
              return res
            }
          }
    
          return 0
        })
      }
    
      return data
    },
    • 排序数据也分三大类型:字符串、数字、日期(时间)
    js
    export const sortValue = (a, b, val) => {
      const dataA = a[val.field]
      const dataB = b[val.field]
      const order = val.order
      const valueType = getColumnFilterValueType(val.column)
    
      switch (valueType) {
        case 'string': {
          return sortString(String(dataA), String(dataB), order)
        }
        case 'number': {
          return sortNumber(dataA, dataB, order)
        }
        case 'date':
        case 'time':
        case 'datetime': {
          return sortDateTime(dataA, dataB, order)
        }
        default: {
          return 0
        }
      }
    }
    • 以数字为例,根据不同的排序条件进行排序
    js
    const sortNumber = (dataA, dataB, order) => {
      // 数字比大小
      return order === 'asc' ? dataA - dataB : dataB - dataA
    }
  • 3、分页page

    js
    currentData () {
      return this.sortData.slice(
        (this.page.currentPage - 1) * this.page.pageSize,
        this.page.currentPage * this.page.pageSize
      )
    },

注意

  • 关于复选数据重复的问题:
    • 数据通过查询,增量累加,不存在单独减少操作,此时不需要考虑复选数据更新;
    • 数据执行操作成功,会对数据重置或删除,此时要更新复选的数据,设置为空;

代码