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

 10740

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

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

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


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


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


使用方式:

1、引入组件

  1. import FilterHeader from '@/components/FilterHeader'

2、注册组件

  1. components: {
  2.   FilterHeader
  3. }

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

  1. <el-table-column label="类型">
  2.   <template slot="header" slot-scope="scope">
  3.     <FilterHeader
  4.     :column="scope.column"
  5.     field-name="type"
  6.     filter-type="checkbox"
  7.     :custom-arr-list="dictList"
  8.     @tableFilter="tableFilter"
  9.     @resetFilter="tableFilterReset"
  10.     />
  11.   </template>
  12. </el-table-column>

组件属性及事件解释

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

FilterHeader组件代码如下:

  1. <template>
  2.   <div style="display: inline-block" @click.stop>
  3.     <el-popover
  4.       ref="popover"
  5.       placement="bottom"
  6.       title="查询条件"
  7.       width="300"
  8.       trigger="click"
  9.     >
  10.       <!-- 单个文本框 -->
  11.       <div v-if="filterType == 'text'">
  12.         <el-input
  13.           v-model.trim="conditions.text"
  14.           size="mini"
  15.           clearable
  16.           placeholder="请输入查询内容"
  17.           @keyup.native.enter="confirm()"
  18.         />
  19.       </div>
  20.       <!-- 数值范围 -->
  21.       <div v-else-if="filterType == 'number'">
  22.         <el-input
  23.           v-model.trim="conditions.number1"
  24.          
  25.           size="mini"
  26.           clearable
  27.           type="number"
  28.           step="0.01"
  29.           placeholder="请输入开始数值"
  30.         />
  31.         <el-input
  32.           v-model.trim="conditions.number2"
  33.          
  34.           size="mini"
  35.           clearable
  36.           step="0.01"
  37.           style="margin-top: 10px"
  38.           placeholder="请输入结束数值"
  39.         />
  40.       </div>
  41.       <!-- 日期-->
  42.       <div v-else-if="filterType == 'date'">
  43.         <el-date-picker
  44.           v-model="conditions.date1"
  45.           type="date"
  46.           clearable
  47.           size="mini"
  48.          
  49.           placeholder="开始时间"
  50.           value-format="yyyy-MM-dd"
  51.         />
  52.         <el-date-picker
  53.           v-model="conditions.date2"
  54.           style="margin-top: 10px"
  55.           type="date"
  56.           size="mini"
  57.           clearable
  58.          
  59.           placeholder="结束时间"
  60.           value-format="yyyy-MM-dd"
  61.         />
  62.       </div>
  63.       <!-- 下拉框-->
  64.       <div v-else-if="filterType == 'select'">
  65.         <el-select
  66.           v-model="conditions.select"
  67.           placeholder="请选择"
  68.          
  69.           size="mini"
  70.           clearable
  71.         >
  72.           <el-option
  73.             v-for="(item, index) in customArrList"
  74.             :key="index"
  75.             :label="item.label"
  76.             :value="item.value"
  77.           />
  78.         </el-select>
  79.       </div>
  80.       <!-- 复选框-->
  81.       <div v-else-if="filterType == 'checkbox'">
  82.         <el-checkbox-group v-model="conditions.checkbox">
  83.           <el-checkbox
  84.             v-for="(item, index) in customArrList"
  85.             :key="index"
  86.             :label="item.value"
  87.            
  88.           >{{ item.label }}</el-checkbox>
  89.         </el-checkbox-group>
  90.       </div>
  91.       <!--单选按钮-->
  92.       <div v-else-if="filterType == 'radio'">
  93.         <el-radio-group v-model="conditions.radio">
  94.           <el-radio
  95.             v-for="(item, index) in customArrList"
  96.             :key="index"
  97.             :label="item.value"
  98.             border
  99.             size="mini"
  100.           >{{ item.label }}</el-radio>
  101.         </el-radio-group>
  102.       </div>
  103.       <!-- confirm 确定框-->
  104.       <div class="text-right mgt10">
  105.         <el-button
  106.           type="warning"
  107.           size="mini"
  108.           @click="reset"
  109.         >重置</el-button>
  110.         <el-button
  111.           type="primary"
  112.           size="mini"
  113.           @click="confirm"
  114.         >确定</el-button>
  115.       </div>
  116.       <!-- 标题-->
  117.       <span
  118.         slot="reference"
  119.         onselectstart="return false"
  120.         oncontextmenu="return false"
  121.        
  122.         :class="labelColor"
  123.       >{{ column.label }} &nbsp;<i />
  124.       </span>
  125.     </el-popover>
  126.   </div>
  127. </template>
  128. <script>
  129. export default {
  130.   name: 'FilterHeader',
  131.   props: {
  132.     column: {
  133.       type: Object,
  134.       defalut: null
  135.     },
  136.     fieldName: {
  137.       type: String,
  138.       defalut: ''
  139.     },
  140.     filterType: {
  141.       type: String,
  142.       defalut: 'txt'
  143.     },
  144.     customArrList: {
  145.       type: Array,
  146.       defalut: []
  147.     }
  148.   },
  149.   data() {
  150.     return {
  151.       conditions: {
  152.         text: '',
  153.         number1: '',
  154.         number2: '',
  155.         date1: '',
  156.         date2: '',
  157.         select: '',
  158.         checkbox: [],
  159.         radio: ''
  160.       }
  161.     }
  162.   },
  163.   computed: {
  164.     // 有条件的话高亮显示标题
  165.     labelColor() {
  166.       switch (this.filterType) {
  167.         case 'text':
  168.           if (this.conditions.text) { return 'heighLight' }
  169.           return ''
  170.         case 'number':
  171.           if (this.conditions.number1 || this.conditions.number2) { return 'heighLight' }
  172.           return ''
  173.         case 'date':
  174.           if (this.conditions.date1 || this.conditions.date2) { return 'heighLight' }
  175.           return ''
  176.         case 'select':
  177.           if (this.conditions.select) { return 'heighLight' }
  178.           return ''
  179.         case 'checkbox':
  180.           if (this.conditions.checkbox.length > 0) { return 'heighLight' }
  181.           return ''
  182.         case 'radio':
  183.           if (this.conditions.radio !== '') { return 'heighLight' }
  184.           return ''
  185.       }
  186.       return ''
  187.     }
  188.   },
  189.   methods: {
  190.     confirm() {
  191.       this.$refs.popover.doClose()
  192.       this.$emit('tableFilter', {
  193.         filterType: this.filterType,
  194.         fieldName: this.fieldName,
  195.         conditions: this.conditions
  196.       })
  197.     },
  198.     reset() {
  199.       switch (this.filterType) {
  200.         case 'text':
  201.           this.conditions.text = ''
  202.           break
  203.         case 'number':
  204.           this.conditions.number1 = ''
  205.           this.conditions.number2 = ''
  206.           break
  207.         case 'date':
  208.           this.conditions.date1 = ''
  209.           this.conditions.date2 = ''
  210.           break
  211.         case 'select':
  212.           this.conditions.select = ''
  213.           break
  214.         case 'checkbox':
  215.           this.conditions.checkbox = []
  216.           break
  217.         case 'radio':
  218.           this.conditions.radio = ''
  219.           break
  220.       }
  221.       this.$refs.popover.doClose()
  222.       this.$emit('resetFilter', {
  223.         filterType: this.filterType,
  224.         fieldName: this.fieldName,
  225.         conditions: this.conditions
  226.       })
  227.     }
  228.   }
  229. }
  230. </script>
  231. <style scoped>
  232.   .label {
  233.     user-select: none;
  234.   }
  235.   .heighLight {
  236.     color: #409eff;
  237.   }
  238.   .filter-radio{
  239.     display: flex;justify-content: space-between;flex-wrap: wrap;
  240.     .el-radio{width: 45%;margin-right: 0}
  241.   }
  242. </style>

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

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

我们在data中定义两个变量tableDataCopy,conditionsFields

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

注:tableDataCopy为tableData的深拷贝

比如我们在列表请求中

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

表格列筛选

  1. tableFilter(data, reset) {
  2.   let flag = true // 判断条件里有没有该列,用来判断是新增还是更新
  3.   let filterData = this.tableDataCopy // 最终过滤信息
  4.   if (!reset) {
  5.   // 参与筛选的列信息,有则更新
  6.   this.conditionsFields.forEach(item => {
  7.     if (item.fieldName === data.fieldName) {
  8.     item.conditions = data.conditions
  9.     flag = false
  10.     }
  11.   })
  12.   // 没有则添加
  13.   if (flag) {
  14.     this.conditionsFields.push(data)
  15.   }
  16.   }
  17.   // 遍历所有筛选条件进行过滤
  18.   this.conditionsFields.filter((fields, index) => {
  19.   filterData = filterData.filter(item => {
  20.     // 文本
  21.     if (fields.filterType === 'text' && fields.conditions.text !== '') {
  22.     return item[fields.fieldName] && item[fields.fieldName].indexOf(fields.conditions.text) > -1
  23.     // 复选框
  24.     } else if (fields.filterType === 'checkbox' && fields.conditions.checkbox.length !== 0) {
  25.     return fields.conditions.checkbox.includes(item[fields.fieldName])
  26.     // 单选按钮
  27.     } else if (fields.filterType === 'radio' && fields.conditions.radio !== '') {
  28.     return item[fields.fieldName] !== null && item[fields.fieldName].toString() === fields.conditions.radio.toString()
  29.     // 日期
  30.     } else if (fields.filterType === 'date' && (fields.conditions.date1 || fields.conditions.date2)) {
  31.     if (!fields.conditions.date1) {
  32.       return item[fields.fieldName] <= fields.conditions.date2
  33.     } else if (!fields.conditions.date2) {
  34.       return item[fields.fieldName] >= fields.conditions.date1
  35.     } else {
  36.       return item[fields.fieldName] >= fields.conditions.date1 && item[fields.fieldName] <= fields.conditions.date2
  37.     }
  38.     // 数值
  39.     } else if (fields.filterType === 'number' && (fields.conditions.number1 || fields.conditions.number2)) {
  40.     if (!fields.conditions.number1) {
  41.       return item[fields.fieldName] <= fields.conditions.number2
  42.     } else if (!fields.conditions.number2) {
  43.       return item[fields.fieldName] >= fields.conditions.number1
  44.     } else {
  45.       return item[fields.fieldName] >= fields.conditions.number1 && item[fields.fieldName] <= fields.conditions.number2
  46.     }
  47.     } else {
  48.     // 遍历完没找到符合条件的,则直接返回
  49.     return item
  50.     }
  51.   })
  52.   })
  53.   this.tableData = this.$set(this, 'tableData', filterData)
  54. }

重置列筛选

  1. tableFilterReset(data) {
  2.   // 清空当前列筛选条件
  3.   this.conditionsFields.forEach((item, index) => {
  4.   if (item.fieldName === data.fieldName) {
  5.     this.conditionsFields.splice(index, 1)
  6.   }
  7.   })
  8.   if (this.conditionsFields.length === 0) {
  9.   // 没有筛选条件了直接请求列表
  10.   this.getList()
  11.   } else {
  12.   // 有筛选条件就再去筛选
  13.   this.tableFilter(data, true)
  14.   }
  15. }

为防止代码中有字符被转义,大家也可以下载完整组件文件

el-table表头自定义筛选的实现el-table筛选组件.zip


本文网址:https://www.zztuku.com/detail-12470.html
站长图库 - el-table表头自定义筛选的实现
申明:如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐