element表格筛选:联动接口查询

276 阅读2分钟

element表格筛选:联动接口查询

element表格组件并不支持后端筛选, 并且官方文档对筛选功能描述十分模糊,
本篇文章是基于element-ui组件, 通过事件监听器、公共样式修改、局部更新表格组件、深拷贝数组实现如下功能:

筛选功能演示(字幕.gif

  1. 筛选联动接口查询
  2. 多选条件筛选
  3. 排他性筛选(只允许一个筛选条件)
  4. 下三角样式重写为漏斗样式
  5. 选中时漏斗高亮
  6. 筛选列表失焦时,漏斗取消高亮
  7. 筛选按钮样式重写(文字改按钮,按钮靠左,按钮禁用淡蓝样式,筛选->确定,重置->清空,两按钮交换位置)

1. 筛选联动接口查询

只需配置如下element属性即可实现:
@filter-change="filterHandler" // 筛选改变事件
:filters="filterParams[item.key]" // 筛选列表
:filtered-value="filterValue[item.key]" // 已筛选的值
:column-key="item.key" // 筛选字段key(用于筛选事件的响应参数)

      <!-- filter-change 为确定筛选方法 -->
      <el-table
        :data="tableData.body"
        row-key="id"
        @filter-change="filterHandler"
      >
        <!-- 
		filters:筛选选项数组
          filtered-value:筛选值
          column-key:筛选字段的key  -->
        <el-table-column
          v-for="item in tableData.head"
          :key="item.key"
          :label="item.name"
          :prop="item.key"
          :filters="filterParams[item.key]"
          :filtered-value="filterValue[item.key]"
          :column-key="item.key"
        >
        </el-table-column>
      </el-table>

<script>
export default {
  data() {
    return {
      filterValue: {} // 筛选值
    },
  computed: {
    /*
    筛选列表:包含所有可筛选的字段
    模板:
    filterParams: {
      connectionStatus: [
        { text: '在线', value: '在线' },
        { text: '离线', value: '离线' }
      ]
    }
    */
    filterParams() {
      const resObj = { alarmSeverityId: [] }
      ;['', '正常', '警告', '次要', '主要', '严重'].forEach((item, index) => {
        if (index !== 0) {
          resObj.alarmSeverityId.push({ text: item, value: index })
        }
      })
      return resObj
    },
  methods: {
    // 联动后端筛选方法
    filterHandler(obj) {
      const key = Object.keys(obj)[0] // 筛选项的key
      this.filterValue = {}
      if (obj[key].length !== 0) {
        this.filterValue[key] = obj[key] // 同步筛选list
      }
      this.getTableData()
    },
        
    // 获取列表数据
    getTableData() {
      const params = {
        pageNum: this.pageNum,
        pageSize: this.pageSize,        
        obj: { ...this.searchForm , ...this.filterValue } // 将筛选值传入请求参数中
      }
      getNetworkElementList(params) // 发起请求
    }
  }
}
</script>

所有代码实现如下

      <!-- :key="Math.random()" 在筛选值变化时刷新漏斗样式 -->
      <!-- filter-change 为确定筛选方法 -->
      <el-table
        :key="Math.random()"
        :data="tableData.body"
        row-key="id"
        @filter-change="filterHandler"
      >
        <!-- 
		filters:筛选选项数组
          filtered-value:筛选值
          column-key:筛选字段的key  -->
        <el-table-column
          v-for="item in tableData.head"
          :key="item.key"
          :label="item.name"
          :prop="item.key"
          :filters="filterParams[item.key]"
          :filtered-value="filterValue[item.key]"
          :column-key="item.key"
        >
          <template slot-scope="scope">
            <template v-if="item.key === 'name'">
              <span class="param-link" @click="openParamTab(scope.row)">
                {{ scope.row.name }}
              </span>
            </template>
            <template v-else>{{ scope.row[item.key] }}</template>
          </template>
        </el-table-column>
      </el-table>


<script>
export default {
  data() {
    return {
      filterValue: {} // 筛选值
    },
  computed: {
    /*
    筛选列表:包含所有可筛选的字段
    模板:
    filterParams: {
      connectionStatus: [
        { text: '在线', value: '在线' },
        { text: '离线', value: '离线' }
      ]
    }
    */
    filterParams() {
      const resObj = { alarmSeverityId: [] }
      ;['', '正常', '警告', '次要', '主要', '严重'].forEach((item, index) => {
        if (index !== 0) {
          resObj.alarmSeverityId.push({ text: item, value: index })
        }
      })
      return resObj
    },
  mounted() {
    this.getTableData()
    document.addEventListener('click', this.clickOutsideHandler) // 点击外部的事件监听器
  },
  beforeDestroy() {
    document.removeEventListener('click', this.clickOutsideHandler) // 注销事件监听器
  },
  methods: {
    // 点击外部时,刷新筛选值
    clickOutsideHandler() {
      const cloneFilterValue = JSON.parse(JSON.stringify(this.filterValue))
      Object.keys(this.filterValue).forEach(key => {
        this.filterValue[key] = []
      })
      this.$nextTick(() => {
        // 重置为此前确定的筛选值
        this.filterValue = cloneFilterValue
      })
    },

    // 联动后端筛选方法
    filterHandler(obj) {
      const key = Object.keys(obj)[0] // 筛选项的key
      this.filterValue = {}
      if (obj[key].length !== 0) {
        this.filterValue[key] = obj[key] // 同步筛选list
      }
      this.getTableData()
    },
        
    // 获取列表数据
    getTableData() {
      const params = {
        pageNum: this.pageNum,
        pageSize: this.pageSize,        
        obj: { ...this.searchForm , ...this.filterValue } // 将筛选值传入请求参数中
      }
      getNetworkElementList(params) // 发起请求
    }
  }
}
</script>

/*全局公共样式*/
<style>
// 筛选框内部样式(文字改按钮,按钮靠左,按钮禁用淡蓝样式,筛选->确定,重置->清空,两按钮交换位置)
.el-table-filter__wrap.el-scrollbar__wrap {
  margin-bottom: 0px !important;
}
.el-table-filter__bottom {
  height: 45px;
  button:after {
    position: absolute;
    background-color: #fff;
    padding: 2px 5px;
    border-radius: 3px;
  }
  button:nth-child(1):after {
    left: 55px;
    content: '确定';
    background-color: $themeColor;
    border: $themeColor 1px solid;
  }
  .is-disabled:nth-child(1):after {
    border: #a8c7fb 1px solid !important;
    background-color: #a8c7fb;
  }

  button:nth-child(2):after {
    left: 6px;
    content: '清除';
    color: #6b6b6b !important;
    border: #989898 1px solid;
  }
  button:nth-child(2):hover:after {
    color: $themeColor !important;
    border: $themeColor 1px solid;
  }
  button {
    color: #fff !important;
  }
}

// 筛选图标样式(使用伪类, 画倒三角和长方形组合为漏斗)
.el-table__column-filter-trigger {
  .el-icon-arrow-down {
    transform: translateY(25%);
    box-sizing: border-box;
    margin-left: 5px;
  }
  .el-icon-arrow-down:before {
    content: '';
    display: inline-block;
    width: 15px;
    height: 15px;
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-top: 7px solid #767575;
  }
  .el-icon-arrow-down:after {
    position: absolute;
    content: '';
    display: inline-block;
    left: 5px;
    height: 13px;
    background-color: #767575;
    width: 4px;
  }
}

// 高亮时添加highlight类, 使用主题色
.cell.highlight {
  color: $tableHeaderColor !important;
}

.cell.highlight .el-table__column-filter-trigger .el-icon-arrow-down:before {
  border-top: 7px solid #508ff6;
}

.cell.highlight .el-table__column-filter-trigger .el-icon-arrow-down:after {
  background-color: #508ff6;
}
</style>