el-table表头自定义筛选的实现

element-ui在国产vue项目中使用的比列还是非常高的,UI框架在帮助我们省力的同时也束缚住了我们的手脚,比如一些复杂的定制化需求使用框架自由的组件并不能满足我们的需求。这种需求假如在一开始就有也比较省事,麻烦就在于使用框架的组件之后产生的新需求要如何应对。

后台系统对table组件的需求是最常见的,不过element-ui的el-table组件只是能满足最基本的需求而已。比如复杂表头,动态列,列拖拽,列筛选,以及大数据的渲染上就不太行了。

今天这篇文章要讲的就是给表头加上自定义的筛选功能,效果如下:

当然还有其它类型就不一一截图了,我根据自己的业务封装了【文本,日期,数值,复选框,单选按钮,下拉框】等通用筛选项,希望对大家有所帮助。

使用方式:

1、引入组件

import FilterHeader from '@/components/FilterHeader'

2、注册组件

components: {
  FilterHeader
}

3、在el-table-column的header插槽中插入组件,如

<el-table-column label="类型">
  <template slot="header" slot-scope="scope">
    <FilterHeader
    :column="scope.column"
    field-name="type"
    filter-type="checkbox"
    :custom-arr-list="dictList"
    @tableFilter="tableFilter"
    @resetFilter="tableFilterReset"
    />
  </template>
</el-table-column>

组件属性及事件解释

:column="scope.column" // 当前列的信息
field-name="type" // 当前字段名
filter-type="checkbox" // 筛选的方式为checkbox即复选框
:custom-arr-list="dictList" // 这个是筛选项的列表,格式为[{label:'',value:''},{label:'',value:''}]
@tableFilter="tableFilter" // 触发筛选
@resetFilter="tableFilterReset" // 触发重置

FilterHeader组件代码如下:

<template>
  <div style="display: inline-block" @click.stop>
    <el-popover
      ref="popover"
      placement="bottom"
      title="查询条件"
      width="300"
      trigger="click"
    >
      <!-- 单个文本框 -->
      <div v-if="filterType == 'text'">
        <el-input
          v-model.trim="conditions.text"
          size="mini"
          clearable
          placeholder="请输入查询内容"
          @keyup.native.enter="confirm()"
        />
      </div>
      <!-- 数值范围 -->
      <div v-else-if="filterType == 'number'">
        <el-input
          v-model.trim="conditions.number1"
         
          size="mini"
          clearable
          type="number"
          step="0.01"
          placeholder="请输入开始数值"
        />
        <el-input
          v-model.trim="conditions.number2"
         
          size="mini"
          clearable
          step="0.01"
          style="margin-top: 10px"
          placeholder="请输入结束数值"
        />
      </div>
      <!-- 日期-->
      <div v-else-if="filterType == 'date'">
        <el-date-picker
          v-model="conditions.date1"
          type="date"
          clearable
          size="mini"
         
          placeholder="开始时间"
          value-format="yyyy-MM-dd"
        />
        <el-date-picker
          v-model="conditions.date2"
          style="margin-top: 10px"
          type="date"
          size="mini"
          clearable
         
          placeholder="结束时间"
          value-format="yyyy-MM-dd"
        />
      </div>
      <!-- 下拉框-->
      <div v-else-if="filterType == 'select'">
        <el-select
          v-model="conditions.select"
          placeholder="请选择"
         
          size="mini"
          clearable
        >
          <el-option
            v-for="(item, index) in customArrList"
            :key="index"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </div>
      <!-- 复选框-->
      <div v-else-if="filterType == 'checkbox'">
        <el-checkbox-group v-model="conditions.checkbox">
          <el-checkbox
            v-for="(item, index) in customArrList"
            :key="index"
            :label="item.value"
           
          >{{ item.label }}</el-checkbox>
        </el-checkbox-group>
      </div>
      <!--单选按钮-->
      <div v-else-if="filterType == 'radio'">
        <el-radio-group v-model="conditions.radio">
          <el-radio
            v-for="(item, index) in customArrList"
            :key="index"
            :label="item.value"
            border
            size="mini"
          >{{ item.label }}</el-radio>
        </el-radio-group>
      </div>
      <!-- confirm 确定框-->
      <div class="text-right mgt10">
        <el-button
          type="warning"
          size="mini"
          @click="reset"
        >重置</el-button>
        <el-button
          type="primary"
          size="mini"
          @click="confirm"
        >确定</el-button>
      </div>
      <!-- 标题-->
      <span
        slot="reference"
        onselectstart="return false"
        oncontextmenu="return false"
       
        :class="labelColor"
      >{{ column.label }} &nbsp;<i />
      </span>
    </el-popover>
  </div>
</template>
<script>
export default {
  name: 'FilterHeader',
  props: {
    column: {
      type: Object,
      defalut: null
    },
    fieldName: {
      type: String,
      defalut: ''
    },
    filterType: {
      type: String,
      defalut: 'txt'
    },
    customArrList: {
      type: Array,
      defalut: []
    }
  },
  data() {
    return {
      conditions: {
        text: '',
        number1: '',
        number2: '',
        date1: '',
        date2: '',
        select: '',
        checkbox: [],
        radio: ''
      }
    }
  },
  computed: {
    // 有条件的话高亮显示标题
    labelColor() {
      switch (this.filterType) {
        case 'text':
          if (this.conditions.text) { return 'heighLight' }
          return ''
        case 'number':
          if (this.conditions.number1 || this.conditions.number2) { return 'heighLight' }
          return ''
        case 'date':
          if (this.conditions.date1 || this.conditions.date2) { return 'heighLight' }
          return ''
        case 'select':
          if (this.conditions.select) { return 'heighLight' }
          return ''
        case 'checkbox':
          if (this.conditions.checkbox.length > 0) { return 'heighLight' }
          return ''
        case 'radio':
          if (this.conditions.radio !== '') { return 'heighLight' }
          return ''
      }
      return ''
    }
  },
  methods: {
    confirm() {
      this.$refs.popover.doClose()
      this.$emit('tableFilter', {
        filterType: this.filterType,
        fieldName: this.fieldName,
        conditions: this.conditions
      })
    },
    reset() {
      switch (this.filterType) {
        case 'text':
          this.conditions.text = ''
          break
        case 'number':
          this.conditions.number1 = ''
          this.conditions.number2 = ''
          break
        case 'date':
          this.conditions.date1 = ''
          this.conditions.date2 = ''
          break
        case 'select':
          this.conditions.select = ''
          break
        case 'checkbox':
          this.conditions.checkbox = []
          break
        case 'radio':
          this.conditions.radio = ''
          break
      }
      this.$refs.popover.doClose()
      this.$emit('resetFilter', {
        filterType: this.filterType,
        fieldName: this.fieldName,
        conditions: this.conditions
      })
    }
  }
}
</script>
<style scoped>
  .label {
    user-select: none;
  }
  .heighLight {
    color: #409eff;
  }
  .filter-radio{
    display: flex;justify-content: space-between;flex-wrap: wrap;
    .el-radio{width: 45%;margin-right: 0}
  }
</style>

如有特殊需求自己可以改一改。组件为了做到通用性,里面并无业务逻辑代码,所有逻辑都在我们的父组件页面中编写。

以下为tableFilter,tableFilterReset方法的业务逻辑代码,大家可以参考

我们在data中定义两个变量tableDataCopyconditionsFields

data(){
  tableData: [], // 表格的数据
  tableDataCopy: {}, // 深度拷贝的tableData对象,用来筛选数据
  conditionsFields: [], // 记录参与筛选的列信息
}

 注:tableDataCopy为tableData的深拷贝

比如我们在列表请求中

getList().then(res=>{
  this.tableData = res.data
  this.tableDataCopy = JSON.parse(JSON.stringify(this.tableData))
})

表格列筛选

tableFilter(data, reset) {
  let flag = true // 判断条件里有没有该列,用来判断是新增还是更新
  let filterData = this.tableDataCopy // 最终过滤信息
  if (!reset) {
  // 参与筛选的列信息,有则更新
  this.conditionsFields.forEach(item => {
    if (item.fieldName === data.fieldName) {
    item.conditions = data.conditions
    flag = false
    }
  })
  // 没有则添加
  if (flag) {
    this.conditionsFields.push(data)
  }
  }
  // 遍历所有筛选条件进行过滤
  this.conditionsFields.filter((fields, index) => {
  filterData = filterData.filter(item => {
    // 文本
    if (fields.filterType === 'text' && fields.conditions.text !== '') {
    return item[fields.fieldName] && item[fields.fieldName].indexOf(fields.conditions.text) > -1
    // 复选框
    } else if (fields.filterType === 'checkbox' && fields.conditions.checkbox.length !== 0) {
    return fields.conditions.checkbox.includes(item[fields.fieldName])
    // 单选按钮
    } else if (fields.filterType === 'radio' && fields.conditions.radio !== '') {
    return item[fields.fieldName] !== null && item[fields.fieldName].toString() === fields.conditions.radio.toString()
    // 日期
    } else if (fields.filterType === 'date' && (fields.conditions.date1 || fields.conditions.date2)) {
    if (!fields.conditions.date1) {
      return item[fields.fieldName] <= fields.conditions.date2
    } else if (!fields.conditions.date2) {
      return item[fields.fieldName] >= fields.conditions.date1
    } else {
      return item[fields.fieldName] >= fields.conditions.date1 && item[fields.fieldName] <= fields.conditions.date2
    }
    // 数值
    } else if (fields.filterType === 'number' && (fields.conditions.number1 || fields.conditions.number2)) {
    if (!fields.conditions.number1) {
      return item[fields.fieldName] <= fields.conditions.number2
    } else if (!fields.conditions.number2) {
      return item[fields.fieldName] >= fields.conditions.number1
    } else {
      return item[fields.fieldName] >= fields.conditions.number1 && item[fields.fieldName] <= fields.conditions.number2
    }
    } else {
    // 遍历完没找到符合条件的,则直接返回
    return item
    }
  })
  })
  this.tableData = this.$set(this, 'tableData', filterData)
}

重置列筛选

tableFilterReset(data) {
  // 清空当前列筛选条件
  this.conditionsFields.forEach((item, index) => {
  if (item.fieldName === data.fieldName) {
    this.conditionsFields.splice(index, 1)
  }
  })
  if (this.conditionsFields.length === 0) {
  // 没有筛选条件了直接请求列表
  this.getList()
  } else {
  // 有筛选条件就再去筛选
  this.tableFilter(data, true)
  }
}

  • 9
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
el-table是一个基于Element UI的表格组件,可以让我们方便地展示数据,并进行排序、筛选等操作。如果要修改el-table表头颜色,可以通过以下步骤进行: 第一步:在el-table组件上设置表头样式 在el-table组件上添加一个“header-style”属性,并设置其值为一个对象,对象中可定义CSS样式,包括表头的背景色、文字颜色等。比如: <el-table :data="tableData" style="width: 100%" :header-style="{background: '#409EFF', color: '#fff'}"> <!-- 具体表格内容 --> </el-table> 第二步:在el-table-column组件上设置单独的表头样式 如果需要针对某个表头单独设置样式,可以在el-table-column组件上设置“label-class-name”属性,属性值可以指定一个样式类名,这个类名可以在外部定义表头的样式。比如: <el-table :data="tableData" style="width: 100%" :header-style="{background: '#409EFF', color: '#fff'}"> <el-table-column prop="name" label="姓名" :label-class-name="'custom-header'"> </el-table-column> </el-table> 在这里,“custom-header”就是一个自定义类名,在外部可以定义这个类名对应的CSS样式,从而设置单独的表头样式。 总体来说,修改el-table表头颜色的最简单方式是通过在el-table组件上设置头部样式,如果需要针对某些特定的表头进行修改,也可以使用el-table-column组件上的“label-class-name”属性进行单独设置。不同的场景下,可以根据需要选择相应的方式进行设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值