element表格自定义筛选

文章目录


前言

提示:这里可以添加本文要记录的大概内容:

...待续


提示:以下是本篇文章正文内容,下面案例可供参考

一、简介

修改el-table的筛选...待续

二、效果展示


三、源码

使用方法

c 复制代码
<el-table-column
  align="center"
  prop="status"
  :column-key="'status'"
>
  <template #header>
    <div class="layout-center-center">
      <span>路由状态</span>
      <table-filter
        placeholder="按路由状态搜索"
        filter-key="status"
        sortable
        :options="routeStatusList"
        @confirm="handleFilter"
        :checked-list="tempFlow.status_list"
        :sequence="tempFlow.sequence"
      ></table-filter>
    </div>
  </template>
  <template #default="{ row }">
    <span v-if="row.status == 0" style="color: green"
      >[{{ row.status }}]{{ row.status_desc }}</span
    >
    <span v-else style="color: red"
      >[{{ row.status }}]{{ row.status_desc }}</span
    >
  </template>
</el-table-column>

组件源码

c 复制代码
<template>
  <div class="table-filter" @click.stop>
    <el-popover
      ref="popoverRef"
      popper-class="table-filter-box"
      placement="bottom"
      :width="250"
      trigger="click"
      @show="handleShow"
      @hide="handleHide"
    >
      <template #reference>
        <el-icon v-if="showParams.showSelectBox"><ArrowUp /></el-icon>
        <el-icon v-if="!showParams.showSelectBox"><ArrowDown /></el-icon>
      </template>
      <section class="table-filter-btns">
        <el-input
          v-if="filter"
          v-model="searchKey"
          :placeholder="placeholder"
          size="mini"
          class="filte-input"
          @input="search"
        />
        <el-divider v-if="filter" />
        <el-scrollbar max-height="200px" ref="scrollbarRef" v-if="filter">
          <div>
            <el-checkbox
              v-model="checkAll"
              label="全部"
              size="large"
              @change="selectAll"
            />
          </div>
          <div
            class="infinite-list-item"
            v-for="option in showOptions"
            :key="option"
          >
            <el-checkbox
              v-model="option.checked"
              :label="option.label"
              size="large"
              @change="selectItem(option.value, option.checked)"
            />
          </div>
        </el-scrollbar>
        <el-divider v-if="filter" />
        <div v-if="props.sortable">
          <el-checkbox v-model="sortable_asc" label="ASC" />
          <el-checkbox v-model="sortable_desc" label="DESC" />
        </div>
        <el-divider v-if="props.sortable" />
        <section class="btns">
          <el-button type="primary" size="small" @click="handleConfirm"
            >筛选</el-button
          >
          <el-button
            size="small"
            color="#ff5722"
            style="color: #fff"
            @click="handleCancel"
            >取消</el-button
          >
        </section>
      </section>
    </el-popover>
    <el-icon v-if="checkedList.length > 0"><Filter /></el-icon>
    <el-icon v-if="sortable_asc"><CaretTop /></el-icon>
    <el-icon v-if="sortable_desc"><CaretBottom /></el-icon>
  </div>
</template>

<script setup>
import { defineProps, reactive, ref, watch } from "vue";
const props = defineProps({
  placeholder: {},
  options: {},
  filterKey: {},
  checkedList: {
    type: Array,
    default: [],
  },
  sequence: {},
  sortable: {
    type: Boolean,
    default: false,
  },
  filter: {
    type: Boolean,
    default: true,
  },
});
let curCheckedList = _.cloneDeep(props.checkedList);
let curSequence = props.sequence;
const emit = defineEmits(["confirm"]);

const scrollbarRef = ref();
const popoverRef = ref();
let searchKey = ref();
let checkAll = ref(true); //默认全选
let showOptions = ref([]);
let showParams = reactive({
  showSelectBox: false, //展示下拉框
});
let timer = ""; //处理输入事件的定时器,一次只允许一个定时器存在,避免过度刷新造成的卡顿
let timer_ = "";
let sortable_asc = ref(false);
let sortable_desc = ref(false);
let ifDoSearch = false; // 是否正在处理输入的数据中...
const init = (sequence) => {
  showOptions.value = _.cloneDeep(props.options);
  if (curCheckedList.length == props.options.length) {
    checkAll.value = true;
  } else {
    checkAll.value = false;
  }
  if (!sequence) {
    sortable_asc.value = false;
    sortable_desc.value = false;
  } else if (sequence == "ASC") {
    sortable_asc.value = true;
  } else if (sequence == "DESC") {
    sortable_desc.value = true;
  }
};
init(curSequence);

// 点击全选
const selectAll = (checked) => {
  if (checked) {
    curCheckedList = [];
    showOptions.value = showOptions.value.map((item) => {
      item.checked = true;
      curCheckedList.push(item.value);
      return item;
    });
  } else {
    showOptions.value = showOptions.value.map((item) => {
      item.checked = false;
      return item;
    });
    curCheckedList = [];
  }
};

// 勾选当前选项
const selectItem = (id, checked) => {
  if (checked) {
    curCheckedList.push(id);
    if (curCheckedList.length == props.options.length) {
      checkAll.value = true;
    }
  } else {
    curCheckedList.splice(curCheckedList.indexOf(id), 1);
    checkAll.value = false;
  }
};

/**
 * @desc 确认事件
 */
const handleConfirm = () => {
  emit("confirm", {
    key: props.filterKey,
    checkedList: curCheckedList,
    sequence: curSequence,
  });
  props.checkedList = _.cloneDeep(curCheckedList);
  props.sequence = curSequence;
  popoverRef.value.hide();
};

/**
 * @desc 取消事件
 */
const handleCancel = () => {
  popoverRef.value.hide();
  curCheckedList = _.cloneDeep(props.checkedList);
  init(props.sequence);
};

// 下拉框展示触发的事件
const handleShow = (e) => {
  showParams.showSelectBox = true;

  if (props.filter) {
    scrollbarRef.value.setScrollTop(0);
  }
};
const handleHide = (e) => {
  showParams.showSelectBox = false;
};

function search(query) {
  if (ifDoSearch) {
    clearTimeout(timer);
    clearTimeout(timer_);
  }

  timer = setTimeout(filterMethod(query), 0);
  ifDoSearch = true;
}

function filterMethod(query) {
  let tmp = [];
  if (query !== "") {
    timer_ = setTimeout(() => {
      props.options.forEach((item) => {
        if (
          item.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
          item.value == -1
        ) {
          tmp.push(item);
        }
      });
      showOptions.value = tmp;
    }, 0);
  } else {
    showOptions.value = props.options;
  }
  ifDoSearch = false;
}

watch(
  () => sortable_asc.value,
  (newValue, oldValue) => {
    if (newValue === oldValue) {
      return;
    } else if (newValue) {
      curSequence = "ASC";
      sortable_desc.value = false;
    } else if (!newValue) {
      curSequence = "";
    }
  }
);

watch(
  () => sortable_desc.value,
  (newValue, oldValue) => {
    if (newValue === oldValue) {
      return;
    } else if (newValue) {
      curSequence = "DESC";
      sortable_asc.value = false;
    } else if (!newValue) {
      curSequence = "";
    }
  }
);
</script>

<style lang="less" scoped>
:deep(.el-divider--horizontal) {
  margin: 12px 0px;
}
:deep(.el-popper) {
  padding: 0px;
}
:deep(.el-popover) {
  padding: 0px;
}
.table-filter {
  display: inline-block;
  cursor: pointer;
}
.table-filter-box {
  height: 25px;
  line-height: 25px;
}
.table-filter-icon {
  font: 500;
  font-size: 18px;
}
.filte-input {
  width: 100%;
}
.btns {
  float: right;
}
.infinite-list {
  padding: 0;
  margin: 0;
  list-style: none;
}
</style>


总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

相关推荐
敲敲了个代码5 小时前
从硬编码到 Schema 推断:前端表单开发的工程化转型
前端·javascript·vue.js·学习·面试·职场和发展·前端框架
张雨zy6 小时前
Pinia 与 TypeScript 完美搭配:Vue 应用状态管理新选择
vue.js·ubuntu·typescript
dly_blog6 小时前
Vue 响应式陷阱与解决方案(第19节)
前端·javascript·vue.js
消失的旧时光-19436 小时前
401 自动刷新 Token 的完整架构设计(Dio 实战版)
开发语言·前端·javascript
console.log('npc')6 小时前
Table,vue3在父组件调用子组件columns列的方法展示弹窗文件预览效果
前端·javascript·vue.js
用户47949283569157 小时前
React Hooks 的“天条”:为啥绝对不能写在 if 语句里?
前端·react.js
我命由我123457 小时前
SVG - SVG 引入(SVG 概述、SVG 基本使用、SVG 使用 CSS、SVG 使用 JavaScript、SVG 实例实操)
开发语言·前端·javascript·css·学习·ecmascript·学习方法
用户47949283569157 小时前
给客户做私有化部署,我是如何优雅搞定 NPM 依赖管理的?
前端·后端·程序员
C_心欲无痕8 小时前
vue3 - markRaw标记为非响应式对象
前端·javascript·vue.js
qingyun9898 小时前
深度优先遍历:JavaScript递归查找树形数据结构中的节点标签
前端·javascript·数据结构