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提供了大量能使我们快速便捷地处理数据的函数和方法。

相关推荐
蓝染-惣右介15 分钟前
【若依RuoYi-Vue | 项目实战】帝可得后台管理系统(二)
java·前端·后端·vue·springboot
我码玄黄41 分钟前
HTML翻牌器:用CSS和HTML元素创造动态数字展示
前端·css·html
-草莓星球杯1 小时前
若依VUE项目安全kind-of postcss vite漏洞扫描和修复
前端·javascript·vue.js
LJ小番茄1 小时前
关于wordPress中的用户登录注册等问题
前端·javascript·css·html·wordpress
小郝同学(恩师白云)2 小时前
SpringMVC后续4
java·服务器·前端
优联前端2 小时前
uni-app-通过vue-cli命令行快速上手
开发语言·前端·vue.js·uni-app·优联前端
点燃银河尽头的篝火(●'◡'●)3 小时前
【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9)
前端·web安全·网络安全·xss
Jiaberrr3 小时前
手把手教你:微信小程序实现语音留言功能
前端·微信小程序·小程序·语音·录音
熊猫在哪3 小时前
安装nuxt3
前端·nuxt.js
安冬的码畜日常4 小时前
【CSS in Depth 2 精译_036】5.6 Grid 网格布局中与对齐相关的属性 + 5.7本章小结
前端·css·css3·html5·网格布局·grid·css网格