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>

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年,AI爆发的一年

公众号&#xff1a;算法一只狗 今年以来&#xff0c;AI呈爆发式发展。在文本生成的领域&#xff0c;涌现出以ChatGPT为代表的生成式大模型。而在文本图像生成方面&#xff0c;有高度自定义的Stable Diffusion&#xff0c;和简单易用上手的Midjournery。多模态领域更是百花齐放&…

外汇天眼:Options与OneTick合作,共同打造全球SAAS分析平台

Options Technology&#xff0c;一家为全球金融领域提供云服务的托管服务提供商&#xff0c;今天宣布与OneMarketData及其旗舰产品OneTick平台的合作。 Options将使OneTick订户能够访问其庞大的市场数据存储库&#xff0c;包括股票、外汇、期货、期权和固定收益数据&#xff0…

OpenAI GPT商店来了! 创业公司打不过就加入?|对话Agent创业公司S2R

文&#xff5c;郝 鑫 1月10日&#xff0c;OpenAI推出了在线商店“GPT Store”。该商店已于昨日开始向付费用户、团队和企业用户推出&#xff0c;商店汇集了用户为各种任务创建的ChatGPT的自定义版本。 2023年初到年末&#xff0c;Agent就像一位来自异域的吉普赛女郎&#…

linux 网络基础配置

将Linux主机接入到网络&#xff0c;需要配置网络相关设置一般包括如下内容&#xff1a; 主机名 iP/netmask (ip地址&#xff0c;网关) 路由&#xff1a;默认网关 网络连接状态 DNS服务器 &#xff08;主DNS服务器 次DNS服务器 第三个DNS服务器&#xff09; 一、…

【System Verilog and UVM实力进阶2】SVA语法

毛主席说过&#xff1a;没有调查就没有发言权。 《SVA介绍——学习SVA语法》系列第二讲 本文还是延续上一篇的风格&#xff0c;语言内容尽可能简单明了&#xff0c;有问题大家相互讨论&#xff0c;共同进步。需要电子书的朋友可以给我发邮件。tommi.weiqq.com 1.16 "ended…

本地远程实时获取无人机采集视频图像(天空端 + jetson nano + 检测分割 + 回传地面端显示)

无线图传设备介绍 2、jetson nano天空端数据采集检测保存 3、本地回传显示 1、无线图传设备介绍 由于本设计考虑将无人机得到检测结果实时回传给地面站显示&#xff0c;因此需要考虑一个远程无线通信设备进行传输。本设计采用思翼HM30图传设备。通过无线图传的wifi将天空端的桌…

2023全球软件研发技术大会(SDCon2023)-核心PPT资料下载

一、峰会简介 本次峰会包含12大会议主题&#xff1a;云原生设施与平台、微服务架构实践、软件质量与效能、大数据实践与前沿、架构设计与演进、高可用与高性能架构、Web与大前端开发、编程语言与平台、AIGC与大模型、推荐系统实践、AI智能应用与研究、机器学习架构实践。 软件…

版本控制背景知识

版本控制背景知识 本文是关于 Git 系列文章的导读&#xff0c;我们先介绍一下版本控制的背景知识。 什么是版本控制 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。它将什么时候、什么人更改了文件的什么内容等信息如实记录下来…

HTML---JavaScript操作DOM对象

目录 文章目录 本章目标 一.DOM对象概念 二.节点访问方法 常用方法&#xff1a; 层次关系访问节点 三.节点信息 四.节点的操作方法 操作节点的属性 创建节点 删除替换节点 五.节点操作样式 style属性 class-name属性 六.获取元素位置 总结 本章目标 了解DOM的分类和节点间的…

超市商品管理系统设计 C++实现

超市商品管理系统设计—C实现 文章目录 超市商品管理系统设计---C实现一、内容要求大纲图 二、源代码&#xff08;包含大量注释&#xff09;1、main.cpp文件2、supermarket.h文件3、supermarket.cpp文件4、administrator.h文件5、administrator.cpp文件6、user.h文件7、user.cp…

数据结构之单调栈、单调队列

今天学习了单调栈还有单调队列的概念和使用&#xff0c;接下来我将对其定义并配合几道习题进行讲解&#xff1a; 首先先来复习一下栈与队列&#xff1a; 然后我们来看一下单调栈的定义&#xff1a; 单调栈中的元素从栈底到栈顶的元素的大小是按照单调递增或者单调递减的关系进…

Programming Abstractions in C阅读笔记:p242-p245

《Programming Abstractions in C》学习第67天&#xff0c;p242-p245总结&#xff0c;总计4页。 一、技术总结 6.2小结主要讲回溯算法及递归算法在迷宫求解中应用&#xff0c;当然&#xff0c;理解然后用代码实现出来还是有些难度的。不过&#xff0c;这并不影响我们进行下一…

关于目标检测任务中,XML(voc格式)标注文件的可视化

1. 前言 最近在弄关于目标检测的任务&#xff0c;因为检测的图片和标签是分开的&#xff0c;可视化效果不明显&#xff0c;也不知道随便下载的数据集&#xff0c;标注信息对不对。网上看了好多代码&#xff0c;代码风格和本人平时不同&#xff0c;看起来麻烦&#xff0c;也不知…

flutter 通过打包参数区分来 打内网 外网包

内网 # 打包内网环境flutter build apk --dart-defineis_intranettrue --dart-defineis_managerAppfalse 外网 # 打包内网环境flutter build apk --dart-defineis_intranettrue --dart-defineis_managerAppfalse env.dart // main.dart class EnvironmentConfig {// 是否…

RHCE9学习指南 第19章 网络时间服务器

19.1 时间同步的必要性 对于一些服务来说对时间要求非常严格&#xff0c;例如&#xff0c;图19-1所示由三台服务器搭建的ceph集群。 图19-1 三台机器搭建的集群对时间要求比较高 这三台服务器的时间必须要保持一样&#xff0c;如果不一样&#xff0c;就会显示报警信息。那么…

Vue基础-搭建Vue运行环境

这篇文章介绍了在Vue.js项目中进行开发环境搭建的关键步骤。包括node.js安装和配置、安装Vue及Vue CLI工具、安装webpack模板、安装vue-router、创建Vue项目等步骤。这篇文章为读者提供了清晰的指南&#xff0c;帮助他们快速搭建Vue.js开发环境&#xff0c;为后续的项目开发奠定…

已设定选项 ‘readonly‘ (请加 ! 强制执行)

这是vim编辑器报的错误&#xff0c;相信很多人都遇到过。在使用vi编辑一个需要sudo权限的文件后&#xff0c;保存的时候出现这样的错误。这个时候很多人做的事情可能就是不保存退出&#xff08;敲命令:q!&#xff09;&#xff0c;然后再以sudo vi打开文件重新编辑一次。如果恰巧…

Django的数据库模型的CharField字段的max_length参数与中文字符数的关系探索(参数max_length的单位是字符个数还是字节数?)

01-清理干净之前的数据库迁移信息 02-根据setting.py中的信息删除掉之前建立的数据库 03-删除之后重新创建数据库 04-models.py中创建数据库模型 from django.db import modelsclass User(models.Model):username models.CharField(max_length4)email models.EmailField(uni…

【makedown自带语法技巧】

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

YOLOv8优化策略:轻量化改进 | 华为Ghostnet,超越谷歌MobileNet | CVPR2020

🚀🚀🚀本文改进:Ghost bottleneck为堆叠Ghost模块 ,与YOLOV8建立轻量C2f_GhostBottleneck 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.Ghostnet介绍 论文: https://arxiv.org/pdf/1911.11907.…