el-table组件实现表头搜索功能

 更新时间:2024年11月23日 12:03:51   作者:weixin_45723246  
文章介绍了如何使用`el-table`组件和`render-header`属性自定义表头,并添加搜索功能,通过`Popover`组件和`Clickoutside`指令实现点击搜索区域外隐藏搜索框,解决了多个表头搜索框共存时的冲突问题,感兴趣的朋友一起看看吧

一,展示效果

请添加图片描述

二,功能介绍

利用el-table组件提供的render-header属性自定义表头渲染内容,包含表头标题和一个搜索图标,图标是一个Popover组件弹出框,点击图标出现下面输入框和搜索按钮,点击搜索区域以外的位置,搜索区域消失,这个使用的是element-uiClickoutside 指令。

三,实现代码

主页面 template 部分:

 <!-- template部分-->
	<el-table  
		  :data="list"
          v-loading="listLoading" 
          ref="table">
       <el-table-column
            v-for="(item, index) in tableHead[activeOption]"
            :key="index + item.prop + item.label"
            :prop="item.prop"
            :label="item.label"
            :min-width="item.width ? item.width : item.label.length * 12 + 50"
            :show-overflow-tooltip="true"
            :align="item.align || 'center'"
            class-name="flexColumn"
            :render-header="(h, row) => NumberRenderHeader(h, row, item)"
            :fixed="item.fixed"
          >
            <template slot-scope="{ row }">
              <span>
                {{ row[item.prop] || "" }}
              </span>
            </template>
          </el-table-column>

主页面 methods部分,其中SearchCom是自定义搜索组件。

    // 表头渲染函数
    NumberRenderHeader(createElement, { column, $index }, item) {
      let self = this;
      if (!item.isHeadSearch) {
        return item.label;
      }
      return createElement("div", [
        createElement("div", {
          domProps: {
            innerHTML: column.label,
          },
        }),
        createElement(SearchCom, {
          props: {
            defaultValue: "", // 默认值
            selectIndex: item.popIndex || $index - 3,
          },
          on: {
            selectChange: (val) => self.selectFruitChange(val, item),
          },
        }),
      ]);
    },

render-header属性:

关于createElement函数:介绍链接

自定义组件部分

<template>
  <el-popover
    placement="bottom"
    width="200"
    trigger="manual"
    v-model="visible"
    @show="showPopover"
    popper-class="charge-item-header-popover aaa"
  >
    <!-- 弹出框内容 -->
    <div class="popover_box">
      <el-input
        placeholder="请输入"
        v-model="selectValue"
        @keyup.enter.native="confirm"
        ref="sInput"
        style="padding: 10px 5px"
      >
      </el-input>
      <el-button @click="confirm">搜索</el-button>
    </div>
    <!-- 触发元素 -->
    <div
      slot="reference"
      style="margin-left: 5px"
      @click.stop="popClick"
      v-clickoutside="closeOver"
    >
      <i class="el-icon-search"></i>
    </div>
  </el-popover>
</template>
<script>
// import Clickoutside from "element-ui/src/utils/clickoutside"; // 使用elementui的 Clickoutside 指令
import Clickoutside from "./clickoutside"; // 使用elementui的 Clickoutside 指令
export default {
  data() {
    return {
      value: "", // 输入框中的值
      visible: false, // 组件显示隐藏控制
      selectValue: "", // 当前选中值
      popperElm: "",
    };
  },
  props: {
    defaultValue: {
      type: String,
      default: "",
    },
    selectIndex: {
      type: Number,
      default: 0,
    },
  },
  mounted() {
    // 解决点击输入框组件关闭问题
    this.popperElm = document.getElementsByClassName(
      "charge-item-header-popover"
    )[this.selectIndex - 1];
  },
  methods: {
    // 点击当前组件之外关闭
    handleOutsideClick(e) {
      setTimeout(() => {
        this.visible = false;
      }, 16);
    },
    // 展示当前组件时 鼠标光标定位到输入框
    showPopover() {
      this.$nextTick(() => {
        this.$refs.sInput.focus();
      });
    },
    // 关闭当前组件
    closeOver() {
      this.visible = false;
    },
    popClick(e) {
      this.visible = !this.visible;
    },
    // 输入文字匹配对象的li项
    confirm() {
      this.$emit("selectChange", this.selectValue);
    },
  },
  directives: {
    Clickoutside, // 引用elementui Clickoutside指令
  },
};
</script>
<style scoped>
.el-input {
  border-bottom: 1px solid #ccc;
}
.el-input--prefix /deep/ .el-input__prefix {
  left: 15px;
}
.popover_box {
  display: flex;
  align-items: center;
  padding: 0 5px;
}
::v-deep .el-input {
  border-bottom: none;
}
</style>
<style>
.charge-item-header-popover {
  padding: 0;
}
.charge-item-header-popover .el-button {
  height: 80%;
}
</style>

四,遇到的问题

点击表格的某个搜索图标,点击输入框,搜索区域消失,控制是否点击目标区域以外的元素是通过Clickoutside 指令实现的,下面是Clickoutside 指令的关键代码:

function createDocumentHandler(el, binding, vnode) {
  return function (mouseup = {}, mousedown = {}) {
    if (
      !vnode ||
      !vnode.context ||
      !mouseup.target ||
      !mousedown.target ||
      el.contains(mouseup.target) ||
      el.contains(mousedown.target) ||
      el === mouseup.target ||
      (vnode.context.popperElm &&
        (vnode.context.popperElm.contains(mouseup.target) ||
          vnode.context.popperElm.contains(mousedown.target)))
    )
      return;
    if (
      binding.expression &&
      el[ctx].methodName &&
      vnode.context[el[ctx].methodName]
    ) {
      vnode.context[el[ctx].methodName]();
    } else {
      el[ctx].bindingFn && el[ctx].bindingFn();
    }
  };
}

其中vnode代表使用自定义指令的元素,vnode.context.popperElm则代表使用自定义指令所在的vue文件中data属性中的数据,若这个值绑定的元素包含鼠标点击的元素(即搜索图标)则Popver弹出框不会消失,否则消失,其中popperElm绑定的元素如下:

  mounted() {
    // 解决点击输入框组件关闭问题
    this.popperElm = document.getElementsByClassName(
      "charge-item-header-popover"
    )[0];
  },

以上说明通过上面方法获取的弹出框元素并不包含搜索图标(两个元素不具有父子关系),但是从控制台检索元素看,两个元素又确实是包含关系,后来想到原因如下

一个表格内包含多个表头搜索字段,而第二个搜索框肯定是不包含第一个搜索框图标的

五,解决

在获取弹出框元素时传给搜索框组件一个索引说明是当前页面中的第几个弹出框

父组件页面

     createElement(SearchCom, {
         props: {
           defaultValue: "", // 默认值
           selectIndex: item.popIndex || 1, //selectIndex代表当前页面的第几个popper弹出框
         },
         on: {
           selectChange: (val) => self.selectFruitChange(val, item),
         },
       }),

自定义弹出框组件

 mounted() {
    // 解决点击输入框组件关闭问题
    this.popperElm = document.getElementsByClassName(
      "charge-item-header-popover"
    )[this.selectIndex - 1];
  },

到此这篇关于el-table组件实现表头搜索的文章就介绍到这了,更多相关el-table表头搜索内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

一,展示效果

请添加图片描述

二,功能介绍

利用el-table组件提供的render-header属性自定义表头渲染内容,包含表头标题和一个搜索图标,图标是一个Popover组件弹出框,点击图标出现下面输入框和搜索按钮,点击搜索区域以外的位置,搜索区域消失,这个使用的是element-uiClickoutside 指令。

三,实现代码

主页面 template 部分:

 <!-- template部分-->
	<el-table  
		  :data="list"
          v-loading="listLoading" 
          ref="table">
       <el-table-column
            v-for="(item, index) in tableHead[activeOption]"
            :key="index + item.prop + item.label"
            :prop="item.prop"
            :label="item.label"
            :min-width="item.width ? item.width : item.label.length * 12 + 50"
            :show-overflow-tooltip="true"
            :align="item.align || 'center'"
            class-name="flexColumn"
            :render-header="(h, row) => NumberRenderHeader(h, row, item)"
            :fixed="item.fixed"
          >
            <template slot-scope="{ row }">
              <span>
                {{ row[item.prop] || "" }}
              </span>
            </template>
          </el-table-column>

主页面 methods部分,其中SearchCom是自定义搜索组件。

    // 表头渲染函数
    NumberRenderHeader(createElement, { column, $index }, item) {
      let self = this;
      if (!item.isHeadSearch) {
        return item.label;
      }
      return createElement("div", [
        createElement("div", {
          domProps: {
            innerHTML: column.label,
          },
        }),
        createElement(SearchCom, {
          props: {
            defaultValue: "", // 默认值
            selectIndex: item.popIndex || $index - 3,
          },
          on: {
            selectChange: (val) => self.selectFruitChange(val, item),
          },
        }),
      ]);
    },

render-header属性:

关于createElement函数:介绍链接

自定义组件部分

<template>
  <el-popover
    placement="bottom"
    width="200"
    trigger="manual"
    v-model="visible"
    @show="showPopover"
    popper-class="charge-item-header-popover aaa"
  >
    <!-- 弹出框内容 -->
    <div class="popover_box">
      <el-input
        placeholder="请输入"
        v-model="selectValue"
        @keyup.enter.native="confirm"
        ref="sInput"
        style="padding: 10px 5px"
      >
      </el-input>
      <el-button @click="confirm">搜索</el-button>
    </div>
    <!-- 触发元素 -->
    <div
      slot="reference"
      style="margin-left: 5px"
      @click.stop="popClick"
      v-clickoutside="closeOver"
    >
      <i class="el-icon-search"></i>
    </div>
  </el-popover>
</template>
<script>
// import Clickoutside from "element-ui/src/utils/clickoutside"; // 使用elementui的 Clickoutside 指令
import Clickoutside from "./clickoutside"; // 使用elementui的 Clickoutside 指令
export default {
  data() {
    return {
      value: "", // 输入框中的值
      visible: false, // 组件显示隐藏控制
      selectValue: "", // 当前选中值
      popperElm: "",
    };
  },
  props: {
    defaultValue: {
      type: String,
      default: "",
    },
    selectIndex: {
      type: Number,
      default: 0,
    },
  },
  mounted() {
    // 解决点击输入框组件关闭问题
    this.popperElm = document.getElementsByClassName(
      "charge-item-header-popover"
    )[this.selectIndex - 1];
  },
  methods: {
    // 点击当前组件之外关闭
    handleOutsideClick(e) {
      setTimeout(() => {
        this.visible = false;
      }, 16);
    },
    // 展示当前组件时 鼠标光标定位到输入框
    showPopover() {
      this.$nextTick(() => {
        this.$refs.sInput.focus();
      });
    },
    // 关闭当前组件
    closeOver() {
      this.visible = false;
    },
    popClick(e) {
      this.visible = !this.visible;
    },
    // 输入文字匹配对象的li项
    confirm() {
      this.$emit("selectChange", this.selectValue);
    },
  },
  directives: {
    Clickoutside, // 引用elementui Clickoutside指令
  },
};
</script>
<style scoped>
.el-input {
  border-bottom: 1px solid #ccc;
}
.el-input--prefix /deep/ .el-input__prefix {
  left: 15px;
}
.popover_box {
  display: flex;
  align-items: center;
  padding: 0 5px;
}
::v-deep .el-input {
  border-bottom: none;
}
</style>
<style>
.charge-item-header-popover {
  padding: 0;
}
.charge-item-header-popover .el-button {
  height: 80%;
}
</style>

四,遇到的问题

点击表格的某个搜索图标,点击输入框,搜索区域消失,控制是否点击目标区域以外的元素是通过Clickoutside 指令实现的,下面是Clickoutside 指令的关键代码:

function createDocumentHandler(el, binding, vnode) {
  return function (mouseup = {}, mousedown = {}) {
    if (
      !vnode ||
      !vnode.context ||
      !mouseup.target ||
      !mousedown.target ||
      el.contains(mouseup.target) ||
      el.contains(mousedown.target) ||
      el === mouseup.target ||
      (vnode.context.popperElm &&
        (vnode.context.popperElm.contains(mouseup.target) ||
          vnode.context.popperElm.contains(mousedown.target)))
    )
      return;
    if (
      binding.expression &&
      el[ctx].methodName &&
      vnode.context[el[ctx].methodName]
    ) {
      vnode.context[el[ctx].methodName]();
    } else {
      el[ctx].bindingFn && el[ctx].bindingFn();
    }
  };
}

其中vnode代表使用自定义指令的元素,vnode.context.popperElm则代表使用自定义指令所在的vue文件中data属性中的数据,若这个值绑定的元素包含鼠标点击的元素(即搜索图标)则Popver弹出框不会消失,否则消失,其中popperElm绑定的元素如下:

  mounted() {
    // 解决点击输入框组件关闭问题
    this.popperElm = document.getElementsByClassName(
      "charge-item-header-popover"
    )[0];
  },

以上说明通过上面方法获取的弹出框元素并不包含搜索图标(两个元素不具有父子关系),但是从控制台检索元素看,两个元素又确实是包含关系,后来想到原因如下

一个表格内包含多个表头搜索字段,而第二个搜索框肯定是不包含第一个搜索框图标的

五,解决

在获取弹出框元素时传给搜索框组件一个索引说明是当前页面中的第几个弹出框

父组件页面

     createElement(SearchCom, {
         props: {
           defaultValue: "", // 默认值
           selectIndex: item.popIndex || 1, //selectIndex代表当前页面的第几个popper弹出框
         },
         on: {
           selectChange: (val) => self.selectFruitChange(val, item),
         },
       }),

自定义弹出框组件

 mounted() {
    // 解决点击输入框组件关闭问题
    this.popperElm = document.getElementsByClassName(
      "charge-item-header-popover"
    )[this.selectIndex - 1];
  },

到此这篇关于el-table组件实现表头搜索的文章就介绍到这了,更多相关el-table表头搜索内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue 页面刷新、重置、更新页面所有数据的示例代码

    vue 页面刷新、重置、更新页面所有数据的示例代码

    Vue.js提供了多种方式来实现页面刷新、重置和更新页面所有数据的功能,下面通过示例代码演示vue 页面刷新、重置、更新页面所有数据,感兴趣的朋友跟随小编一起看看吧
    2024-01-01
  • Vue表单组件进阶之如何打造属于你的自定义v-model

    Vue表单组件进阶之如何打造属于你的自定义v-model

    在Vue中自定义组件是一个强大的功能,它允许你将可重用的代码封装成独立的模块,从而提高开发效率和代码的可维护性,这篇文章主要介绍了Vue表单组件进阶之如何打造属于你的自定义v-model的相关资料,需要的朋友可以参考下
    2025-11-11
  • vue的注意规范之v-if 与 v-for 一起使用教程

    vue的注意规范之v-if 与 v-for 一起使用教程

    这篇文章主要介绍了vue的注意规范之v-if 与 v-for 一起使用方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • 基于前端VUE+ElementUI实现table行上移或下移功能(支持跨页移动)

    基于前端VUE+ElementUI实现table行上移或下移功能(支持跨页移动)

    有时候需要前端实现上移和下移功能,下面这篇文章主要给大家介绍了关于如何基于前端VUE+ElementUI实现table行上移或下移(支持跨页移动)的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • Vue前端开发之实现交错过渡动画效果

    Vue前端开发之实现交错过渡动画效果

    这篇文章主要为大家详细介绍了如何通过Vue实现交错过渡动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-11-11
  • Vue实现pdf在线预览功能的示例代码

    Vue实现pdf在线预览功能的示例代码

    这篇文章主要为大家详细介绍了如何使用Vue实现pdf在线预览功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-03-03
  • Vue-cli 如何将px转化为rem适配移动端

    Vue-cli 如何将px转化为rem适配移动端

    这篇文章主要介绍了Vue-cli 如何将px转化为rem适配移动端,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-07-07
  • vue2.0使用swiper组件实现轮播的示例代码

    vue2.0使用swiper组件实现轮播的示例代码

    下面小编就为大家分享一篇vue2.0使用swiper组件实现轮播的示例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • vue路由懒加载工作原理

    vue路由懒加载工作原理

    Vue路由懒加载是一种优化技术,旨在减少应用程序的初始加载时间并提高性能,这篇文章给大家介绍vue路由懒加载的相关知识,感兴趣的朋友跟随小编一起看看吧
    2024-05-05
  • Element中Slider滑块的具体使用

    Element中Slider滑块的具体使用

    这篇文章主要介绍了Element中Slider滑块的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07

最新评论