实现功能截图:

在这里插入图片描述

代码

selectFilterHeader.vue 组件
<template>
  <el-popover
    placement="bottom"
    width="200"
    trigger="manual"
    v-model="visible"
    @show="showPopover"
    popper-class="charge-item-header-popover"
  >
    <el-input
      prefix-icon="el-icon-search"
      placeholder="请输入"
      v-model="value"
      @input="confirm"
      @keyup.enter.native="confirm"
      ref="sInput"
      style="padding: 10px;"
    ></el-input>
    <ul class="filter-ul">
      <li
        @click="onCheckItem(item)"
        v-for="(item, index) in searchFilters"
        :key="index"
        :class="{ 'is-active': isActive(item) }"
      >{{item.text}}</li>
    </ul>
    <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 指令
export default {
  inject: ["reload"],
  data() {
    return {
      value: "", // 输入框中的值
      visible: false, // 组件显示隐藏控制
      selectValue: "", // 当前选中值
      searchFilters: this.filters, // 匹配到的filters
    };
  },
  props: {
    defaultValue: {
      type: String,
      default: ""
    },
    filters: {
      type: Array,
      default: function() {
        return [];
      }
    }
  },
  created() {
    if (this.filters.filter(item => item.value == "").length === 0) {
      this.filters.unshift({ text: "全部", value: "" });
    }
    this.searchFilters = this.filters;
  },
  watch: {
    // 选中 当前选中值
    defaultValue(newVal, oldVal) {
      let self = this;
      self.value = "";
      this.searchFilters = this.filters;
      self.selectValue = newVal;
    }
  },
  mounted() {
    // 解决点击输入框组件关闭问题
    this.popperElm = document.querySelector('.charge-item-header-popover')
  },
  methods: {
    // 点击当前组件之外关闭
    handleOutsideClick(e) {
      setTimeout(() => {
        this.visible = false;
      }, 16);
    },
    // filter 添加active样式
    isActive(filter) {
      return filter.value === this.selectValue;
    },
    // 选中某一项 提交父组件选中数据
    onCheckItem(item) {
      this.selectValue = item.value;
      let self = this;
      self.$emit("selectChange", self.selectValue);
      this.visible = false;
    },
    // 展示当前组件时 鼠标光标定位到输入框
    showPopover() {
      this.$nextTick(() => {
        this.$refs.sInput.focus();
      });
    },
    // 关闭当前组件
    closeOver() {
      this.visible = false;
    },
    popClick(e) {
      this.visible = !this.visible;
    },
    // 输入文字匹配对象的li项
    confirm() {
      this.searchFilters = this.filters.filter(
        item => item.text.indexOf(this.value) > -1
      );
    }
  },
  directives: {
    Clickoutside, // 引用elementui Clickoutside指令
  }
};
</script>
<style scoped>
.el-input {
  border-bottom: 1px solid #ccc;
}
.el-input--prefix /deep/ .el-input__prefix {
  left: 15px;
}
.filter-ul {
  padding: 5px 0;
  margin: 0;
  list-style: none;
  min-width: 100px;
  max-height: 300px;
  overflow: auto;
}
.filter-ul li {
  line-height: 36px;
  padding: 0 12px;
  cursor: pointer;
  font-size: 12px;
}
.filter-ul li:hover {
  background-color: #ecf5ff;
  color: #66b1ff;
}

.filter-ul li.is-active {
  background-color: #409eff;
  color: #fff;
}
</style>
<style>
.charge-item-header-popover {
  padding: 0;
}
</style>
table组件中 引用:

在这里插入图片描述

<template>
	<div>
      <el-table :data="tempTableData" style="width: 50%;">
        <template v-for="(col, index) in exampleCols">
          <el-table-column 
            v-if="col.prop !== 'fruit'"
            :prop="col.prop"
            :label="col.label"
            :key="index">
            <template slot-scope="scope">{{ (scope.row[col.prop])}}</template>
          </el-table-column>
          <el-table-column 
            v-else
            :prop="col.prop"
            :label="col.label"
            :key="index"
            :render-header="exampleRenderHeader">
            <template slot-scope="scope">{{ (scope.row[col.prop])}}</template>
          </el-table-column>
        </template>
      </el-table>
    </div>
</template>
<script>
import selectFilterHeader from "./selectFilterHeader.vue";
export default {
	created() {
    	this.tempTableData = this.tableData;
    },
    data() {
    	return {
			fruit: '',
		      exampleCols: [
		        {
		          label: "姓名",
		          prop: "name",
		        },
		        {
		          label: "地址",
		          prop: "address",
		        },
		        {
		          label: "水果",
		          prop: "fruit",
		        },
		      ],
		      exampleFilters: [
		        {text: '苹果', value: '苹果'},
		        {text: '香蕉', value: '香蕉'},
		        {text: '猕猴桃', value: '猕猴桃'},
		        {text: '西瓜', value: '西瓜'},
		      ],
		      tempTableData: [],
		      tableData: [
		        {
		          name: '王小虎',
		          address: '上海市普陀区金沙江路 1518 弄',
		          fruit: '苹果'
		        }, {
		          name: '王小虎',
		          address: '上海市普陀区金沙江路 1517 弄',
		          fruit: '香蕉'
		        }, {
		          name: '王小虎',
		          address: '上海市普陀区金沙江路 1519 弄',
		          fruit: '猕猴桃'
		        }, {
		          name: '王小虎',
		          address: '上海市普陀区金沙江路 1516 弄',
		          fruit: '西瓜'
		        },{
		          name: '王小虎',
		          address: '上海市普陀区金沙江路 1518 弄',
		          fruit: '苹果'
		        },
		      ],
		}
    },
    methods: {
    	// render-header 渲染方法
		exampleRenderHeader(createElement, { column, $index }) {
	      let self = this;
	      return createElement("div", [
	        createElement("div", {
	          style: self.fruit ? "color: #409EFF" : '',
	          domProps: {
	            innerHTML: column.label
	          }
	        }),
	        createElement(selectFilterHeader, {
	          style: "cursor: pointer;",
	          // 组件 prop
	          props: {
	            defaultValue: self.fruit, // 默认值
	            filters: self.exampleFilters
	          },
	          // 事件监听器在 `on` 属性内,
	          // 但不再支持如 `v-on:keyup.enter` 这样的修饰器。
	          // 需要在处理函数中手动检查 keyCode。
	          on: {
	            selectChange: self.selectFruitChange
	          }
	        })
	      ]);
	    },
	    selectFruitChange(value) {
	      this.fruit = value;
	      this.tempTableData = this.tableData.filter(item => item.fruit.indexOf(value) > -1)
	    },
	},
}
</script>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐