Vue+Element Ui实现el-table自定义表头下拉选择表头筛选

用vue+element ui开发管理系统时,使用el-table做表格,当表格列过多的时候,想要做成可选表头的,实现表格列的筛选显示,效果如下:

代码文件结构:

废话不多说,直接上代码:

第一步:新建名为 TableHeaderRender.vue 的文件

<template>
  <el-popover
    placement="bottom"
    width="200"
    trigger="manual"
    v-model="visible"
    @show="showPopover"
    popper-class="table-header-popover"
  >
    <div class="table-header-popover-template">
      <el-input
        placeholder="请输入内容"
        v-model="value"
        size="small"
        clearable
        @keyup.enter.native="confirm"
        ref="sInput"
      >
        <!-- <el-button slot="append" icon="el-icon-search" @click="confirm"> -->
        <!-- </el-button> -->
      </el-input>
    </div>
    <div class="el-table-filter__bottom">
      <button @click="confirm">筛选</button>
      <button @click="resetData">重置</button>
    </div>
    <span
      slot="reference"
      style="margin-left: 5px"
      @click.stop="popClick"
      v-click-outside="closeOver"
    >
      <i
        class="filter-icon el-icon-search"
        :style="{ color: iconColor ? '#9a4b9b' : '#909399' }"
      ></i>
      <!-- <i class="el-icon-search" :style="{'color':iconColor}" ></i> -->
      <!-- <svg
        viewBox="64 64 896 896"
        data-icon="search"
        width="1em"
        height="1em"
        fill="currentColor"
        :style="{
          color: iconColor ? '#9A4B9B' : '',
          'margin-right': '2px',
          cursor: 'pointer',
        }"
      >
        <path
          d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0 0 11.6 0l43.6-43.5a8.2 8.2 0 0 0 0-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
        ></path>
      </svg> -->
    </span>
  </el-popover>
</template>

<script>
export default {
  name: "tableHeaderRender",
  data() {
    return {
      // input 绑定的值
      value: "",
      visible: false,
      iconColor: false,
    };
  },
  props: {
    tableColumn: {
      type: Object,
      default: () => {},
    },
    columnProp: {
      type: String,
      default: "",
    },
    defaultValue: {
      type: String,
      default: "",
    },
    inputFilteredMap: {
      type: Object,
      default: () => {},
    },
  },
  created() {
    this.value = this.defaultValue;
    this.iconColor = this.value.trim() ? true : false;
  },
  methods: {
    showPopover() {
      this.$nextTick(() => {
        this.$refs.sInput.focus();
      });
    },
    resetData() {
      console.log("reset");
      this.value = "";
      this.visible = false;
      this.iconColor = false;
      const self = this;
      if (this.inputFilteredMap[self.columnProp]) {
        delete this.inputFilteredMap[self.columnProp];
      }
      self.$emit("resetChangeMethod", this.tableColumn, self.columnProp);
    },
    closeOver() {
      this.visible = false;
    },
    popClick(e) {
      // e.stopPropagation()
      this.visible = !this.visible;
    },
    confirm() {
      this.visible = false;
      if (this.value.trim()) {
        this.iconColor = true;
        this.inputFilteredMap[this.columnProp] = this.value;
        this.$emit(
          "filterInputMethod",
          this.tableColumn,
          this.inputFilteredMap
        );
      } else {
        // 如果搜索input输入为空,等同重置
        this.resetData();
      }
    },
  },

  directives: {
    clickOutside: {
      bind(el, binding, vnode) {
        function clickHandler(e) {
          // 这里判断点击的元素是否是本身,是本身,则返回
          if (el.contains(e.target)) {
            return false;
          }
          // 判断指令中是否绑定了函数
          if (binding.expression) {
            // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
            binding.value(e);
          }
        }
        // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
        el.__vueClickOutside__ = clickHandler;
        document.addEventListener("click", clickHandler);
      },
      update() {},
      unbind(el, binding) {
        // 解除事件监听
        document.removeEventListener("click", el.__vueClickOutside__);
        delete el.__vueClickOutside__;
      },
    },
  },
};
</script>

<style>
.filter-icon {
  font-size: 14px;
  color: #909399;
  cursor: pointer;
  font-weight: 400;
}
.table-header-popover {
  padding: 0;
}
.table-header-popover .table-header-popover-template {
  margin: 10px;
}
</style>

第二步:新建名为 operateTable.vue 的文件

<template>
  <div class="operateTable">
    <el-dropdown
      size="small"
      trigger="click"
      v-if="options.columnsSelect || options.columnsTreeSelect"
      class="column-dropdown"
    >
      <el-button style="padding: 9px 10px!important" size="small">
        <i style="font-size: 12px" class="el-icon-menu"></i>
        <i class="el-icon-arrow-down el-icon--right"></i>
      </el-button>
      <el-dropdown-menu slot="dropdown">
        <div style="margin:10px;" class="caoz_ft_warp" v-if="isInit||isSave">
          <el-button
            v-if="isInit"
            size="small"
            type="primary" 
            plain
            style="width:70px;"
            @click="initColumns(true)"
          >初始化</el-button>
          <el-button
            v-if="isSave"
            size="small"
            type="primary" 
            plain
            style="width:70px;"
            @click="$emit('saveSettingColumns',checkedList)"
           >保存</el-button>
        </div>
        <div style="margin:10px;" class="caoz_ft_warp">
          <el-input size="small" placeholder="请输入关键字" v-model="cloumnKeyword" clearable></el-input>
        </div>
        <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange" style="padding-left:10px;">Select All</el-checkbox>
        <el-checkbox-group
          v-if="!options.columnsTreeSelect"
          v-model="checkedList"
          style="max-height: 300px"
          @change="handleCheckedCitiesChange"
        >
          <div class="checkboxScorll">
            <template v-for="(option, index) in checkBoxOptions">
              <template v-if="cloumnKeyword && option.toLowerCase().indexOf(cloumnKeyword.toLowerCase())>-1">
                <el-checkbox
                  :key="index"
                  class="checkbox"
                  :label="option"
                ></el-checkbox>
              </template>
              <template v-else-if="!cloumnKeyword">
                <el-checkbox
                  :key="index"
                  class="checkbox"
                  :label="option"
                ></el-checkbox>
              </template>
              <template v-else></template>
            </template>
          </div>
        </el-checkbox-group>
        <div v-else class="checkboxTree">
          <el-tree
            ref="tree"
            :check-on-click-node="true"
            :data="treeColumn"
            show-checkbox
            node-key="label"
            :default-expanded-keys="defaultExpanded"
            :default-checked-keys="defaultChecked"
            :props="{
              children: 'children',
              label: 'label',
            }"
            @check="checkChange"
            style="max-height: 300px; overflow-y: auto"
          >
          </el-tree>
        </div>
      </el-dropdown-menu>
    </el-dropdown>
    <el-table
      id="iTable"
      ref="operateTable"
      border
      :data="dataSource"
      :stripe="options.stripe"
      :highlight-current-row="options.highlightCurrentRow"
      :max-height="options.maxHeight"
      :size="options.size"
      :fit="options.fit"
      :show-header="options.showHeader"
      :empty-text="options.emptyText"
      :default-sort="options.defaultSort"
      :row-key="getRowKeys"
      :default-expand-all="options.defaultExpandAll"
      :tree-props="options.treeProps"
      :lazy="options.lazy"
      :load="load"
      @cell-mouse-enter="cellMouseEnter"
      @cell-mouse-leave="cellMouseLeave"
      @cell-click="cellClick"
      @cell-dblclick="cellDblclick"
      @row-click="rowClick"
      @row-contextmenu="rowContextmenu"
      @row-dblclick="rowDblclick"
      @header-click="headerClick"
      @header-contextmenu="headerContextmenu"
      @sort-change="sortChange"
      @select="select"
      @select-all="selectAll"
      @selection-change="checkboxSelected"
      @filter-change="filterChange"
    >
      <slot name="expandRow"></slot>
      <!-- 复选框 -->
      <el-table-column
        :reserve-selection="options.reserveSelection"
        :key="0"
        type="selection"
        :selectable="selectable"
        width="40"
        align="left"
        v-if="options.showCheckBox"
        :resizable="false"
      >
      </el-table-column>
      <el-table-column
        ref="fixedColumn"
        label="操作"
        align="left"
        :width="operates.dropDown ? '50' : operates.width"
        :fixed="operates.fixed"
        :min-width="operates.minwidth"
        :resizable="operates.resizable"
        v-if="operates.list.length > 0"
      >
        <template slot-scope="scope">
          <!-- 操作列 不折叠 全为icon-->
          <div
            class="operate-group"
            v-if="!operates.dropDown && !operates.isText"
          >
            <template
              v-for="item in operates.list[0] instanceof Array
                ? operates.list[scope.$index]
                : operates.list"
            >
              <div class="item" v-if="item.show" :key="item.id">
                <el-switch
                  v-if="item.type === 'switch'"
                  v-model="scope.row[item.prop]"
                  active-color="#13ce66"
                  @change="item.method(scope.$index, scope.row)"
                ></el-switch>
                <el-tooltip
                  v-else-if="item.type === 'tooltipIcon'"
                  :enterable="false"
                  effect="light"
                  placement="bottom"
                >
                  <div slot="content">{{ item.tooltip }}</div>
                  <el-button 
                    type="primary" 
                    plain 
                    :icon="item.icon"
                    size="mini" 
                    :disabled="item.disabled"
                    @click="item.method(scope.$index, scope.row)"
                  ></el-button>
                </el-tooltip>
                <el-button 
                  v-else-if="item.type === 'icon'"
                  type="primary" 
                  plain 
                  :icon="item.icon"
                  size="mini" 
                  :disabled="item.disabled"
                  @click="item.method(scope.$index, scope.row)"
                ></el-button>
              </div>
            </template>
          </div>
          <!-- 操作列 不折叠 全为文字-->
          <div
            class="operate-group"
            v-if="!operates.dropDown && operates.isText"
          >
            <template
              v-for="item in operates.list[0] instanceof Array
                ? operates.list[scope.$index]
                : operates.list"
            >
              <div class="item" v-if="item.show" :key="item.id">
                <el-button
                  size="small"
                  type="text"
                  :disabled="item.disabled"
                  @click.native.prevent="item.method(scope.$index, scope.row)"
                  >{{ item.label }}</el-button
                >
              </div>
            </template>
          </div>
          <!-- 操作列 折叠下拉-->
          <div class="operate-group" v-else-if="operates.dropDown">
            <el-dropdown
              @command="handleCommand"
              trigger="hover"
              placement="bottom-start"
            >
              <span class="el-dropdown-link">
                <i class="el-icon-s-unfold" style="font-size: 16px;"></i>
              </span>
              <!-- 根据operates.list 来渲染操作列下拉的内容 -->
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item
                  v-for="(item, index) in operates.list[0] instanceof Array
                    ? operates.list[scope.$index]
                    : operates.list"
                  :disabled="item.disabled"
                  :key="index"
                  :command="composeValue(item, scope.row, scope.$index)"
                  >{{ item.label }}</el-dropdown-item
                >
              </el-dropdown-menu>
            </el-dropdown>
          </div>
        </template>
      </el-table-column>
      <!--region 数据列-->
      <template v-for="column in columns">
        <!-- :filter-method="column.filters ? column.filterMethod : undefined" -->
        <!-- v-if="
            options.columnsSelect || options.columnsTreeSelect
              ? checkedList.includes(column.label)
              : true
          " -->
        <el-table-column
          v-if="
            options.columnsSelect || options.columnsTreeSelect
              ? checkedList.includes(column.label)
              : true
          "
          :prop="column.prop"
          :key="column.label"
          :label="column.label"
          align="left"
          :width="column.width"
          :min-width="column.minwidth"
          :resizable="column.resizable"
          :sortable="column.sortable"
          :filters="column.filters"
          :filter-method="column.filters ? column.filterMethod : undefined"
          :filtered-value="column.filteredValue"
          :fixed="column.fixed"
          :column-key="column.prop"
        >
          <template slot="header" slot-scope="scope"
            >{{ column.label }}
            <TableHeaderRender
              v-if="column.filterInput"
              :columnProp="column.prop"
              :tableColumn="scope.column"
              :defaultValue="column.defaultValue"
              :inputFilteredMap="inputFilteredMap"
              @filterInputMethod="filterInputMethod"
              @resetChangeMethod="resetChangeMethod"
            ></TableHeaderRender>
          </template>
          <!-- :filtered-value="column.filteredValue" -->
          <template slot-scope="scope">
            <!-- 如果传进来的column没有render函数执行以下代码 -->
            <template v-if="!column.render">
              <!-- 如果传进来的column没有render函数但有formatter函数执行以下代码 -->
              <template v-if="column.formatter">
                <span v-html="column.formatter(scope.row, column)"></span>
              </template>
              <!-- 如果传进来的column既没有render函数也没有formatter函数执行以下代码 -->
              <template v-else>
                <span>{{ scope.row[column.prop] }}</span>
              </template>
            </template>
            <!-- 如果传进来的column有render函数执行以下代码 -->
            <template v-else>
              <expand-dom
                :column="column"
                :row="scope.row"
                :render="column.render"
                :index="scope.$index"
              ></expand-dom>
            </template>
          </template>
        </el-table-column>
      </template>
      <!--endregion-->
    </el-table>
  </div>
</template>

<script>
import TableHeaderRender from "./TableHeaderRender.vue";
export default {
  name: "OperateTable",
  props: {
    // 表格的数据源
    dataSource: {
      type: Array,
      default: () => [],
    },
    // 需要展示的列
    columns: {
      type: Array,
      default: () => [{}],
    },
    // table 表格的控制参数
    options: {
      type: Object,
      default: () => {
        return {
          stripe: true, // 是否为斑马纹 table
        };
      },
    },
    // 操作按钮组 === label: 文本,show:是否显示,icon:按钮图标,disabled:是否禁用,method:回调方法, 等等
    operates: {
      type: Object,
      default: () => {
        return {
          list: [],
        };
      },
    },
    defaultSelectedColumn: {
      type: Array,
      default: () => [],
    },
    defaultColumn: {
      type: Array,
      default: () => [],
    },
    totalColumn: {
      type: Array,
      default: () => [],
    },
    treeColumn: {
      type: Array,
      default: () => [],
    },
    defaultChecked: {
      type: Array,
      default: () => [],
    },
    defaultExpanded: {
      type: Array,
      default: () => [],
    },
    isInit: {
      type: Boolean,
      default: false
    },
    isSave: {
      type: Boolean,
      default: false
    }
  },
  components: {
    TableHeaderRender,
    expandDom: {
      functional: true,
      props: {
        row: Object,
        render: Function,
        index: Number,
        column: {
          type: Object,
          default: null,
        },
      },
      render: (h, ctx) => {
        const params = {
          row: ctx.props.row,
          index: ctx.props.index,
        };
        if (ctx.props.column) params.column = ctx.props.column;
        return ctx.props.render(h, params);
      },
    },
  },
  data() {
    return {
      cloumnKeyword:"",//字段关键字搜索
      isIndeterminate:true,//全选状态
      checkAll:false,//字段全选
      checkBoxOptions: [], // 全部表头
      checkedList: [], // 选中表头
      count: 0, // 用于判断表格是否刚渲染
      isCheckBoxSort: false, // 用于判断是否是由自定义数据列引发的排序
      // 以下是之前放于vuex中用于记录状态
      preCheckedList: [], // 前一次的checkbox
      // 排序的状态
      sort: {
        prop: "",
        order: "",
        label: "",
      },
      // 筛选的状态
      checkBoxFilteredMap: {},
      // input 所有的筛选
      inputFilteredMap: {},
      // columns label及prop对应的键值对
      columnsLabelMap: {}
    };
  },
  watch: {
    // 监听defaultColumn,若这个发生变化,代表传入的默认column变化,即数据表格发生了切换
    defaultColumn() {
      this.initColumns();
    },
    checkedList() {
      // if(this.checkedList.length>0){
      //   this.$emit("selectedColumn",this.checkedList);
      // }
      // 处理当点击checkbox显示的是排序列时,恢复排序列的显示
      let showLabelArray = this.checkboxShowLabel();
      console.log("showLabelArray", showLabelArray);
      // if (value.length !== 0) {
      //   value.map((item) => {
      //     this.handleStatusRevert(item);
      //   });
      this.columns.map((column, index) => {
        this.handleStatusRevert(column, index, showLabelArray);
      });
    },
  },
  created() {
    this.normalizeColumnsLabelMap();
  },
  mounted() {
    if (!this.options.columnsTreeSelect) {
      this.checkedList = this.$props.defaultColumn;
      this.checkBoxOptions = this.$props.totalColumn;
    } else {
      this.checkedList = this.$refs.tree
        .getCheckedNodes()
        .map((item) => item.label);
    }
    // 挂载时将defaultSort属性传给vuex
    this.handleDefaultSort();
  },
  // 动态切换表头的时候闪烁是因为表头重新计算高度导致的,以下方法解决此bug
  beforeUpdate() {
    this.$nextTick(() => {
      //在数据加载完,重新渲染表格
      this.$refs["operateTable"].doLayout();
    });
  },
  methods: {
    //全选字段
    handleCheckAllChange(val){
      this.checkedList = val ? this.checkBoxOptions : [];
      this.isIndeterminate = false;
    },
    //反选
    handleCheckedCitiesChange(value){
      let checkedCount = value.length;
      this.checkAll = checkedCount === this.checkBoxOptions.length;
      this.isIndeterminate = checkedCount > 0 && checkedCount < this.checkBoxOptions.length;
    },
    //初始化字段
    initColumns(flag){
      if(flag){
        this.checkedList = this.$props.defaultSelectedColumn;
      }else{
        this.checkedList = this.$props.defaultColumn;
      }
      this.checkBoxOptions = this.$props.totalColumn;
    },
    // 处理判断checkbox 点击时,显示的是哪个字段名
    checkboxShowLabel() {
      // 判断显示的字段是哪个字段,如果是树形,可能有多个,故更改为数组接收
      let value = [];
      console.log("this.checkedList", this.checkedList);
      if (this.count === 0) {
        this.saveCheckedList(this.checkedList);
        // this.$componentsStore.commit("table/saveCheckedList", this.checkedList);
        this.count++;
      } else {
        if (this.checkedList.length > this.preCheckedList.length) {
          for (let index = 0; index < this.checkedList.length; index++) {
            if (!this.preCheckedList.includes(this.checkedList[index])) {
              value.push(this.checkedList[index]);
            }
            // if (this.checkedList[index] !== this.preCheckedList[index]) {
            //   value = this.checkedList[index];
            // }
          }
        }
        this.saveCheckedList(this.checkedList);
        // this.$componentsStore.commit("table/saveCheckedList", this.checkedList);
      }
      return value;
    },
    // 处理sort\filterd由隐藏变为显示状态的恢复
    handleStatusRevert(column, index, showLabelArray) {
      let compareLabel = column.label;
      if (showLabelArray.includes(compareLabel)) {
        // 如果是有checkbox 筛选的字段,恢复筛选
        let filteredValue =
          this.checkBoxFilteredMap[this.columnsLabelMap[compareLabel]];
        // 如果是有input 筛选的字段,恢复筛选
        let filteredInputValue =
          this.inputFilteredMap[this.columnsLabelMap[compareLabel]];
        this.columns[index].filteredValue = filteredValue;
        this.columns[index].defaultValue = filteredInputValue;
        this.$nextTick(() => {
          this.$refs.operateTable.store.states.columns.map((column) => {
            if (column.filteredValue && column.filteredValue.length) {
              this.$refs.operateTable.store.commit("filterChange", {
                column,
                values: column.filteredValue,
                silent: true,
              });
            }
          });
        });
      } else {
        this.columns[index].filteredValue = [];
        this.columns[index].defaultValue = "";
      }
      // 如果是有排序的字段,恢复排序
      if (showLabelArray.includes(this.sort.label)) {
        this.$nextTick(() => {
          //在数据加载完,重新渲染表格
          this.isCheckBoxSort = true;
          this.$refs.operateTable.sort(this.sort.prop, this.sort.order);
        });
      }
      /**
      // 如果是有checkbox 筛选的字段,恢复筛选
      let filteredValue = this.checkBoxFilteredMap[this.columnsLabelMap[value]];
      // 如果是有input 筛选的字段,恢复筛选
      let filteredInputValue = this.inputFilteredMap[
        this.columnsLabelMap[value]
      ];
      for (let i = 0; i < this.columns.length; i++) {
        if (this.columns[i].label === value) {
          this.columns[i].filteredValue = filteredValue;
          this.columns[i].defaultValue = filteredInputValue;
          this.$nextTick(() => {
            this.$refs.operateTable.store.states.columns.map((column) => {
              if (column.filteredValue && column.filteredValue.length) {
                console.log("!11");
                this.$refs.operateTable.store.commit("filterChange", {
                  column,
                  values: column.filteredValue,
                  silent: true,
                });
              }
            });
          });
        } else {
          this.columns[i].filteredValue = [];
          this.columns[i].defaultValue = "";
        }
      }
      // for (let i = 0; i < this.columns.length; i++) {
      //   if (this.columns[i].label === value) {
      //     this.columns[i].defaultValue = filteredInputValue;
      //   } else {
      //     this.columns[i].defaultValue = "";
      //   }
      // }
      // 如果是有排序的字段,恢复排序
      if (value === this.sort.label) {
        this.$nextTick(() => {
          //在数据加载完,重新渲染表格
          this.isCheckBoxSort = true;
          this.$refs.operateTable.sort(this.sort.prop, this.sort.order);
        });
      }
      */
    },
    // 处理生成columns 的label prop键值对
    normalizeColumnsLabelMap() {
      this.columns.map((column) => {
        this.columnsLabelMap[column.label] = column.prop;
      });
    },
    filterInputMethod(column, inputFilteredMap) {
      console.log("column, inputFilteredMap", column, inputFilteredMap);
      this.inputFilteredMap = inputFilteredMap;
      this.$emit("filterInputMethod", column, inputFilteredMap);
    },
    resetChangeMethod(tableColumn, columnProp) {
      this.$emit("resetChangeMethod", tableColumn, this.inputFilteredMap);
    },
    cellMouseEnter(row, column, cell, event) {
      this.$emit("cell-mouse-enter", row, column, cell, event);
    },
    cellMouseLeave(row, column, cell, event) {
      this.$emit("cell-mouse-leave", row, column, cell, event);
    },
    cellClick(row, column, cell, event) {
      this.$emit("cell-click", row, column, cell, event);
    },
    cellDblclick(row, column, cell, event) {
      this.$emit("cell-dblclick", row, column, cell, event);
    },
    rowClick(row, column, event) {
      this.$emit("row-click", row, column, event);
    },
    rowContextmenu(row, column, event) {
      this.$emit("row-contextmenu", row, column, event);
    },
    rowDblclick(row, column, event) {
      this.$emit("row-dblclick", row, column, event);
    },
    headerClick(column, event) {
      this.$emit("header-click", column, event);
    },
    headerContextmenu(column, event) {
      this.$emit("header-contextmenu", column, event);
    },
    sortChange(sortObj) {
      this.changeSort(sortObj);
      // this.$componentsStore.commit("table/changeSort", sortObj);
      if (!this.isCheckBoxSort) {
        this.$emit("sort-change", sortObj);
      }
      // 还原isCheckBoxSort
      this.isCheckBoxSort = false;
    },
    handleDefaultSort() {
      if (this.options.defaultSort !== undefined) {
        let column = { label: "" };
        // for (let index = 0; index < this.columns.length; index++) {
        //   if (this.columns[index].prop === this.options.defaultSort.prop) {
        //     column.label = this.columns[index].label;
        //     break;
        //   }
        // }
        column.label = this.columnsLabelMap[this.options.defaultSort.prop];
        this.changeSort({
          ...this.options.defaultSort,
          column,
        });
      }
    },
    // 点击操作的下拉项目后触发事件
    handleCommand(command) {
      if (command.method) {
        command.method(command.index, command.row, command.label);
      }
    },
    // 点击dropDown传参方法
    composeValue(item, row, index) {
      return {
        label: item.label,
        row: row,
        index: index,
        method: item.method,
      };
    },
    select(selection, row) {
      this.$emit("select", selection, row);
    },
    selectAll(selection) {
      this.$emit("select-all", selection);
    },
    checkboxSelected(selection) {
      this.$emit("selection-change", selection);
    },
    selectable(row, index) {
      let data = true;
      this.$emit("selectable", row, index, (val) => {
        data = val;
      });
      return data;
    },
    getRowKeys(row) {
      let data;
      for (let index = 0; index < this.dataSource.length; index++) {
        if (row === this.dataSource[index]) {
          data = index;
          break;
        }
      }
      // this.dataSource.map((item, index) => {
      //   if (row === item) {
      //     data = index;
      //   }
      // });
      this.$emit("row-key", row, (val) => {
        data = val;
      });
      return data;
    },
    load(tree, treeNode, resolve) {
      this.$emit("load", tree, treeNode, resolve);
    },
    // 记录表格总的筛选状态,用于列显示隐藏时保存checkbox状态
    filterChange(filters) {
      let currKey = Object.keys(filters)[0];
      if (filters[currKey].length === 0) {
        delete this.checkBoxFilteredMap[currKey];
      } else {
        this.checkBoxFilteredMap[currKey] = filters[currKey];
      }
      this.$emit("filter-change", filters);
    },
    checkChange(nodeObj, checkObj) {
      this.checkedList = checkObj.checkedNodes.map((item) => {
        return item.label;
      });
    },
    // 之前写在vuex里的方法
    changeSort(sort) {
      this.sort.prop = sort.prop;
      this.sort.order = sort.order;
      this.sort.label = sort.column.label;
    },
    saveCheckedList(preCheckedList) {
      this.preCheckedList = preCheckedList;
    },
  },
};
</script>

<style>
    .operateTable{
        position: relative;
        width: 100%;
    }
    .operateTable .column-dropdown{
        position: absolute;
        right: 0px;
        top: -42px;
        z-index: 99;
    }
    .caoz_ft_warp{
      text-align: center;
    }
    .caoz_ft_warp .el-input.is-active .el-input__inner, .caoz_ft_warp .el-input__inner:focus{
        border-color: #9A4B9B;
        outline: 0;
    }
    .el-checkbox__input.is-checked .el-checkbox__inner,.el-checkbox__input.is-indeterminate .el-checkbox__inner {
        background-color: #9a4b9b;
        border-color: #9a4b9b;
    }
    .el-checkbox__inner:hover {
        border-color: #9A4B9B;
    }
    .el-checkbox__input.is-focus .el-checkbox__inner{
        border-color: #9A4B9B;
    }
    .el-checkbox__input.is-checked+.el-checkbox__label {
        color: #9A4B9B;
    }
    .checkboxScorll .el-checkbox__input.is-checked + .el-checkbox__label {
        color: #666;
    }
    .column-dropdown .el-button{margin-right: 0 !important;min-width:0;}
    .column-dropdown .el-button:focus, .el-button:hover{
        color: #9A4B9B;
        border-color: #e1c9e1;
        background-color: #f5edf5;
    }
    .checkboxScorll {
        max-height: 300px;
        overflow-y: auto;
    }
    .checkboxScorll .checkbox {
        display: block;
        margin-top: 10px;
        padding-left: 20px;
    }
</style>

第三步:在页面中引入operateTable并使用

<template>
  <div class="tableView">
    <div class="content">
      <operateTable
        v-loading="loading"
        :dataSource="operateTableData"
        :columns="operateTableColumns"
        :options="operateTableOption"
        :defaultColumn="defaultColumns"
        :totalColumn="totalColumns"
        :defaultSelectedColumn="defaultSelectedColumn"
        @sort-change="sortChange"
        @saveSettingColumns="saveSettingColumns"
      ></operateTable>
    </div>
  </div>
</template>

<script>
import operateTable from "./components/operateTable.vue";
export default {
  name: "",
  components: {
    operateTable,
  },
  data() {
    return {
      loading: false,
      operateTableData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
        },
        {
          date: "2016-05-04",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1517 弄",
        },
        {
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1519 弄",
        },
        {
          date: "2016-05-03",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1516 弄",
        },
      ],
      operateTableColumns: [
        {
          prop: "action",
          label: "操作",
          width: 100,
          fixed: true,
          render: (h, params) => {
            return h(
              "div",
              {
                class: "operate-group",
              },
              [
                h(
                  "el-tooltip",
                  {
                    props: {
                      content: "处理",
                      placement: "bottom",
                      enterable: false,
                      effect: "light",
                    },
                    class: "item",
                  },
                  [
                    h("i", {
                      props: {},
                      class: "el-icon-edit",
                      on: {
                        click: () => {
                          console.log(params.row);
                        },
                      },
                    }),
                  ]
                ),
              ]
            );
          },
        },
        {
          prop: "date",
          label: "日期",
          minwidth: 150,
          sortable: "custom",
        },
        {
          prop: "name",
          label: "姓名",
          minwidth: 150,
          sortable: "custom",
        },
        {
          prop: "address",
          label: "地址",
          minwidth: 150,
          sortable: "custom",
        },
      ],
      operateTableOption: {
        stripe: true, // 是否为斑马纹 table
        highlightCurrentRow: true, // 是否要高亮当前行
        columnsSelect: true,
        maxHeight: 300,
      },
      defaultColumns: ["操作", "日期", "姓名", "地址"],
      totalColumns: ["操作", "日期", "姓名", "地址"],
      //所有用户默认勾选的列  用于初始化
      defaultSelectedColumn: [],
    };
  },
  methods: {
    //表头排序
    sortChange(column, prop, order) {
      if (column.order === "ascending") {
        this.orderfield = column.prop;
        this.orderby = "ASC";
      } else if (column.order === "descending") {
        this.orderfield = column.prop;
        this.orderby = "DESC";
      } else {
        this.orderfield = "";
        this.orderby = "";
      }
      //   this.getTabldHandle();
    },
    //保存自定义字段
    saveSettingColumns(data) {
      console.log(data);
    },
  },
  mounted() {},
};
</script>

<style>
.tableView {
  width: 100%;
  height: 100%;
}
.content {
  padding: 60px;
}
.disableIcon {
  color: #c0c4cc;
  cursor: not-allowed;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yongqiang Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值