// 操作按钮组 === label: 文本,show:是否显示,icon:按钮图标,disabled:是否禁用,method:回调方法, 等等。defaultColumns: ["操作", "日期", "姓名", "地址"],totalColumns: ["操作", "日期", "姓名", "地址"],_el-table 列头可选">
当前位置:   article > 正文

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

el-table 列头可选

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

代码文件结构:

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

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

  1. <template>
  2.   <el-popover
  3.     placement="bottom"
  4.     width="200"
  5.     trigger="manual"
  6.     v-model="visible"
  7.     @show="showPopover"
  8.     popper-class="table-header-popover"
  9.   >
  10.     <div class="table-header-popover-template">
  11.       <el-input
  12.         placeholder="请输入内容"
  13.         v-model="value"
  14.         size="small"
  15.         clearable
  16.         @keyup.enter.native="confirm"
  17.         ref="sInput"
  18.       >
  19.         <!-- <el-button slot="append" icon="el-icon-search" @click="confirm"> -->
  20.         <!-- </el-button> -->
  21.       </el-input>
  22.     </div>
  23.     <div class="el-table-filter__bottom">
  24.       <button @click="confirm">筛选</button>
  25.       <button @click="resetData">重置</button>
  26.     </div>
  27.     <span
  28.       slot="reference"
  29.       style="margin-left: 5px"
  30.       @click.stop="popClick"
  31.       v-click-outside="closeOver"
  32.     >
  33.       <i
  34.         class="filter-icon el-icon-search"
  35.         :style="{ color: iconColor ? '#9a4b9b' : '#909399' }"
  36.       ></i>
  37.       <!-- <i class="el-icon-search" :style="{'color':iconColor}" ></i> -->
  38.       <!-- <svg
  39.         viewBox="64 64 896 896"
  40.         data-icon="search"
  41.         width="1em"
  42.         height="1em"
  43.         fill="currentColor"
  44.         :style="{
  45.           color: iconColor ? '#9A4B9B' : '',
  46.           'margin-right': '2px',
  47.           cursor: 'pointer',
  48.         }"
  49.       >
  50.         <path
  51.           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"
  52.         ></path>
  53.       </svg> -->
  54.     </span>
  55.   </el-popover>
  56. </template>
  57. <script>
  58. export default {
  59.   name"tableHeaderRender",
  60.   data() {
  61.     return {
  62.       // input 绑定的值
  63.       value"",
  64.       visiblefalse,
  65.       iconColorfalse,
  66.     };
  67.   },
  68.   props: {
  69.     tableColumn: {
  70.       typeObject,
  71.       default() => {},
  72.     },
  73.     columnProp: {
  74.       typeString,
  75.       default"",
  76.     },
  77.     defaultValue: {
  78.       typeString,
  79.       default"",
  80.     },
  81.     inputFilteredMap: {
  82.       typeObject,
  83.       default() => {},
  84.     },
  85.   },
  86.   created() {
  87.     this.value = this.defaultValue;
  88.     this.iconColor = this.value.trim() ? true : false;
  89.   },
  90.   methods: {
  91.     showPopover() {
  92.       this.$nextTick(() => {
  93.         this.$refs.sInput.focus();
  94.       });
  95.     },
  96.     resetData() {
  97.       console.log("reset");
  98.       this.value = "";
  99.       this.visible = false;
  100.       this.iconColor = false;
  101.       const self = this;
  102.       if (this.inputFilteredMap[self.columnProp]) {
  103.         delete this.inputFilteredMap[self.columnProp];
  104.       }
  105.       self.$emit("resetChangeMethod"this.tableColumn, self.columnProp);
  106.     },
  107.     closeOver() {
  108.       this.visible = false;
  109.     },
  110.     popClick(e) {
  111.       // e.stopPropagation()
  112.       this.visible = !this.visible;
  113.     },
  114.     confirm() {
  115.       this.visible = false;
  116.       if (this.value.trim()) {
  117.         this.iconColor = true;
  118.         this.inputFilteredMap[this.columnProp] = this.value;
  119.         this.$emit(
  120.           "filterInputMethod",
  121.           this.tableColumn,
  122.           this.inputFilteredMap
  123.         );
  124.       } else {
  125.         // 如果搜索input输入为空,等同重置
  126.         this.resetData();
  127.       }
  128.     },
  129.   },
  130.   directives: {
  131.     clickOutside: {
  132.       bind(el, binding, vnode) {
  133.         function clickHandler(e) {
  134.           // 这里判断点击的元素是否是本身,是本身,则返回
  135.           if (el.contains(e.target)) {
  136.             return false;
  137.           }
  138.           // 判断指令中是否绑定了函数
  139.           if (binding.expression) {
  140.             // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
  141.             binding.value(e);
  142.           }
  143.         }
  144.         // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
  145.         el.__vueClickOutside__ = clickHandler;
  146.         document.addEventListener("click", clickHandler);
  147.       },
  148.       update() {},
  149.       unbind(el, binding) {
  150.         // 解除事件监听
  151.         document.removeEventListener("click", el.__vueClickOutside__);
  152.         delete el.__vueClickOutside__;
  153.       },
  154.     },
  155.   },
  156. };
  157. </script>
  158. <style>
  159. .filter-icon {
  160.   font-size14px;
  161.   color#909399;
  162.   cursor: pointer;
  163.   font-weight400;
  164. }
  165. .table-header-popover {
  166.   padding0;
  167. }
  168. .table-header-popover .table-header-popover-template {
  169.   margin10px;
  170. }
  171. </style>

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

  1. <template>
  2.   <div class="operateTable">
  3.     <el-dropdown
  4.       size="small"
  5.       trigger="click"
  6.       v-if="options.columnsSelect || options.columnsTreeSelect"
  7.       class="column-dropdown"
  8.     >
  9.       <el-button style="padding: 9px 10px!important" size="small">
  10.         <i style="font-size: 12px" class="el-icon-menu"></i>
  11.         <i class="el-icon-arrow-down el-icon--right"></i>
  12.       </el-button>
  13.       <el-dropdown-menu slot="dropdown">
  14.         <div style="margin:10px;" class="caoz_ft_warp" v-if="isInit||isSave">
  15.           <el-button
  16.             v-if="isInit"
  17.             size="small"
  18.             type="primary" 
  19.             plain
  20.             style="width:70px;"
  21.             @click="initColumns(true)"
  22.           >初始化</el-button>
  23.           <el-button
  24.             v-if="isSave"
  25.             size="small"
  26.             type="primary" 
  27.             plain
  28.             style="width:70px;"
  29.             @click="$emit('saveSettingColumns',checkedList)"
  30.            >保存</el-button>
  31.         </div>
  32.         <div style="margin:10px;" class="caoz_ft_warp">
  33.           <el-input size="small" placeholder="请输入关键字" v-model="cloumnKeyword" clearable></el-input>
  34.         </div>
  35.         <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange" style="padding-left:10px;">Select All</el-checkbox>
  36.         <el-checkbox-group
  37.           v-if="!options.columnsTreeSelect"
  38.           v-model="checkedList"
  39.           style="max-height: 300px"
  40.           @change="handleCheckedCitiesChange"
  41.         >
  42.           <div class="checkboxScorll">
  43.             <template v-for="(option, index) in checkBoxOptions">
  44.               <template v-if="cloumnKeyword && option.toLowerCase().indexOf(cloumnKeyword.toLowerCase())>-1">
  45.                 <el-checkbox
  46.                   :key="index"
  47.                   class="checkbox"
  48.                   :label="option"
  49.                 ></el-checkbox>
  50.               </template>
  51.               <template v-else-if="!cloumnKeyword">
  52.                 <el-checkbox
  53.                   :key="index"
  54.                   class="checkbox"
  55.                   :label="option"
  56.                 ></el-checkbox>
  57.               </template>
  58.               <template v-else></template>
  59.             </template>
  60.           </div>
  61.         </el-checkbox-group>
  62.         <div v-else class="checkboxTree">
  63.           <el-tree
  64.             ref="tree"
  65.             :check-on-click-node="true"
  66.             :data="treeColumn"
  67.             show-checkbox
  68.             node-key="label"
  69.             :default-expanded-keys="defaultExpanded"
  70.             :default-checked-keys="defaultChecked"
  71.             :props="{
  72.               children: 'children',
  73.               label: 'label',
  74.             }"
  75.             @check="checkChange"
  76.             style="max-height: 300px; overflow-y: auto"
  77.           >
  78.           </el-tree>
  79.         </div>
  80.       </el-dropdown-menu>
  81.     </el-dropdown>
  82.     <el-table
  83.       id="iTable"
  84.       ref="operateTable"
  85.       border
  86.       :data="dataSource"
  87.       :stripe="options.stripe"
  88.       :highlight-current-row="options.highlightCurrentRow"
  89.       :max-height="options.maxHeight"
  90.       :size="options.size"
  91.       :fit="options.fit"
  92.       :show-header="options.showHeader"
  93.       :empty-text="options.emptyText"
  94.       :default-sort="options.defaultSort"
  95.       :row-key="getRowKeys"
  96.       :default-expand-all="options.defaultExpandAll"
  97.       :tree-props="options.treeProps"
  98.       :lazy="options.lazy"
  99.       :load="load"
  100.       @cell-mouse-enter="cellMouseEnter"
  101.       @cell-mouse-leave="cellMouseLeave"
  102.       @cell-click="cellClick"
  103.       @cell-dblclick="cellDblclick"
  104.       @row-click="rowClick"
  105.       @row-contextmenu="rowContextmenu"
  106.       @row-dblclick="rowDblclick"
  107.       @header-click="headerClick"
  108.       @header-contextmenu="headerContextmenu"
  109.       @sort-change="sortChange"
  110.       @select="select"
  111.       @select-all="selectAll"
  112.       @selection-change="checkboxSelected"
  113.       @filter-change="filterChange"
  114.     >
  115.       <slot name="expandRow"></slot>
  116.       <!-- 复选框 -->
  117.       <el-table-column
  118.         :reserve-selection="options.reserveSelection"
  119.         :key="0"
  120.         type="selection"
  121.         :selectable="selectable"
  122.         width="40"
  123.         align="left"
  124.         v-if="options.showCheckBox"
  125.         :resizable="false"
  126.       >
  127.       </el-table-column>
  128.       <el-table-column
  129.         ref="fixedColumn"
  130.         label="操作"
  131.         align="left"
  132.         :width="operates.dropDown ? '50' : operates.width"
  133.         :fixed="operates.fixed"
  134.         :min-width="operates.minwidth"
  135.         :resizable="operates.resizable"
  136.         v-if="operates.list.length > 0"
  137.       >
  138.         <template slot-scope="scope">
  139.           <!-- 操作列 不折叠 全为icon-->
  140.           <div
  141.             class="operate-group"
  142.             v-if="!operates.dropDown && !operates.isText"
  143.           >
  144.             <template
  145.               v-for="item in operates.list[0] instanceof Array
  146.                 ? operates.list[scope.$index]
  147.                 : operates.list"
  148.             >
  149.               <div class="item" v-if="item.show" :key="item.id">
  150.                 <el-switch
  151.                   v-if="item.type === 'switch'"
  152.                   v-model="scope.row[item.prop]"
  153.                   active-color="#13ce66"
  154.                   @change="item.method(scope.$index, scope.row)"
  155.                 ></el-switch>
  156.                 <el-tooltip
  157.                   v-else-if="item.type === 'tooltipIcon'"
  158.                   :enterable="false"
  159.                   effect="light"
  160.                   placement="bottom"
  161.                 >
  162.                   <div slot="content">{{ item.tooltip }}</div>
  163.                   <el-button 
  164.                     type="primary" 
  165.                     plain 
  166.                     :icon="item.icon"
  167.                     size="mini" 
  168.                     :disabled="item.disabled"
  169.                     @click="item.method(scope.$index, scope.row)"
  170.                   ></el-button>
  171.                 </el-tooltip>
  172.                 <el-button 
  173.                   v-else-if="item.type === 'icon'"
  174.                   type="primary" 
  175.                   plain 
  176.                   :icon="item.icon"
  177.                   size="mini" 
  178.                   :disabled="item.disabled"
  179.                   @click="item.method(scope.$index, scope.row)"
  180.                 ></el-button>
  181.               </div>
  182.             </template>
  183.           </div>
  184.           <!-- 操作列 不折叠 全为文字-->
  185.           <div
  186.             class="operate-group"
  187.             v-if="!operates.dropDown && operates.isText"
  188.           >
  189.             <template
  190.               v-for="item in operates.list[0] instanceof Array
  191.                 ? operates.list[scope.$index]
  192.                 : operates.list"
  193.             >
  194.               <div class="item" v-if="item.show" :key="item.id">
  195.                 <el-button
  196.                   size="small"
  197.                   type="text"
  198.                   :disabled="item.disabled"
  199.                   @click.native.prevent="item.method(scope.$index, scope.row)"
  200.                   >{{ item.label }}</el-button
  201.                 >
  202.               </div>
  203.             </template>
  204.           </div>
  205.           <!-- 操作列 折叠下拉-->
  206.           <div class="operate-group" v-else-if="operates.dropDown">
  207.             <el-dropdown
  208.               @command="handleCommand"
  209.               trigger="hover"
  210.               placement="bottom-start"
  211.             >
  212.               <span class="el-dropdown-link">
  213.                 <i class="el-icon-s-unfold" style="font-size: 16px;"></i>
  214.               </span>
  215.               <!-- 根据operates.list 来渲染操作列下拉的内容 -->
  216.               <el-dropdown-menu slot="dropdown">
  217.                 <el-dropdown-item
  218.                   v-for="(item, index) in operates.list[0] instanceof Array
  219.                     ? operates.list[scope.$index]
  220.                     : operates.list"
  221.                   :disabled="item.disabled"
  222.                   :key="index"
  223.                   :command="composeValue(item, scope.row, scope.$index)"
  224.                   >{{ item.label }}</el-dropdown-item
  225.                 >
  226.               </el-dropdown-menu>
  227.             </el-dropdown>
  228.           </div>
  229.         </template>
  230.       </el-table-column>
  231.       <!--region 数据列-->
  232.       <template v-for="column in columns">
  233.         <!-- :filter-method="column.filters ? column.filterMethod : undefined" -->
  234.         <!-- v-if="
  235.             options.columnsSelect || options.columnsTreeSelect
  236.               ? checkedList.includes(column.label)
  237.               : true
  238.           " -->
  239.         <el-table-column
  240.           v-if="
  241.             options.columnsSelect || options.columnsTreeSelect
  242.               ? checkedList.includes(column.label)
  243.               : true
  244.           "
  245.           :prop="column.prop"
  246.           :key="column.label"
  247.           :label="column.label"
  248.           align="left"
  249.           :width="column.width"
  250.           :min-width="column.minwidth"
  251.           :resizable="column.resizable"
  252.           :sortable="column.sortable"
  253.           :filters="column.filters"
  254.           :filter-method="column.filters ? column.filterMethod : undefined"
  255.           :filtered-value="column.filteredValue"
  256.           :fixed="column.fixed"
  257.           :column-key="column.prop"
  258.         >
  259.           <template slot="header" slot-scope="scope"
  260.             >{{ column.label }}
  261.             <TableHeaderRender
  262.               v-if="column.filterInput"
  263.               :columnProp="column.prop"
  264.               :tableColumn="scope.column"
  265.               :defaultValue="column.defaultValue"
  266.               :inputFilteredMap="inputFilteredMap"
  267.               @filterInputMethod="filterInputMethod"
  268.               @resetChangeMethod="resetChangeMethod"
  269.             ></TableHeaderRender>
  270.           </template>
  271.           <!-- :filtered-value="column.filteredValue" -->
  272.           <template slot-scope="scope">
  273.             <!-- 如果传进来的column没有render函数执行以下代码 -->
  274.             <template v-if="!column.render">
  275.               <!-- 如果传进来的column没有render函数但有formatter函数执行以下代码 -->
  276.               <template v-if="column.formatter">
  277.                 <span v-html="column.formatter(scope.row, column)"></span>
  278.               </template>
  279.               <!-- 如果传进来的column既没有render函数也没有formatter函数执行以下代码 -->
  280.               <template v-else>
  281.                 <span>{{ scope.row[column.prop] }}</span>
  282.               </template>
  283.             </template>
  284.             <!-- 如果传进来的column有render函数执行以下代码 -->
  285.             <template v-else>
  286.               <expand-dom
  287.                 :column="column"
  288.                 :row="scope.row"
  289.                 :render="column.render"
  290.                 :index="scope.$index"
  291.               ></expand-dom>
  292.             </template>
  293.           </template>
  294.         </el-table-column>
  295.       </template>
  296.       <!--endregion-->
  297.     </el-table>
  298.   </div>
  299. </template>
  300. <script>
  301. import TableHeaderRender from "./TableHeaderRender.vue";
  302. export default {
  303.   name"OperateTable",
  304.   props: {
  305.     // 表格的数据源
  306.     dataSource: {
  307.       typeArray,
  308.       default() => [],
  309.     },
  310.     // 需要展示的列
  311.     columns: {
  312.       typeArray,
  313.       default() => [{}],
  314.     },
  315.     // table 表格的控制参数
  316.     options: {
  317.       typeObject,
  318.       default() => {
  319.         return {
  320.           stripetrue// 是否为斑马纹 table
  321.         };
  322.       },
  323.     },
  324.     // 操作按钮组 === label: 文本,show:是否显示,icon:按钮图标,disabled:是否禁用,method:回调方法, 等等
  325.     operates: {
  326.       typeObject,
  327.       default() => {
  328.         return {
  329.           list: [],
  330.         };
  331.       },
  332.     },
  333.     defaultSelectedColumn: {
  334.       typeArray,
  335.       default() => [],
  336.     },
  337.     defaultColumn: {
  338.       typeArray,
  339.       default() => [],
  340.     },
  341.     totalColumn: {
  342.       typeArray,
  343.       default() => [],
  344.     },
  345.     treeColumn: {
  346.       typeArray,
  347.       default() => [],
  348.     },
  349.     defaultChecked: {
  350.       typeArray,
  351.       default() => [],
  352.     },
  353.     defaultExpanded: {
  354.       typeArray,
  355.       default() => [],
  356.     },
  357.     isInit: {
  358.       typeBoolean,
  359.       defaultfalse
  360.     },
  361.     isSave: {
  362.       typeBoolean,
  363.       defaultfalse
  364.     }
  365.   },
  366.   components: {
  367.     TableHeaderRender,
  368.     expandDom: {
  369.       functionaltrue,
  370.       props: {
  371.         rowObject,
  372.         renderFunction,
  373.         indexNumber,
  374.         column: {
  375.           typeObject,
  376.           defaultnull,
  377.         },
  378.       },
  379.       render(h, ctx) => {
  380.         const params = {
  381.           row: ctx.props.row,
  382.           index: ctx.props.index,
  383.         };
  384.         if (ctx.props.column) params.column = ctx.props.column;
  385.         return ctx.props.render(h, params);
  386.       },
  387.     },
  388.   },
  389.   data() {
  390.     return {
  391.       cloumnKeyword:"",//字段关键字搜索
  392.       isIndeterminate:true,//全选状态
  393.       checkAll:false,//字段全选
  394.       checkBoxOptions: [], // 全部表头
  395.       checkedList: [], // 选中表头
  396.       count0// 用于判断表格是否刚渲染
  397.       isCheckBoxSortfalse// 用于判断是否是由自定义数据列引发的排序
  398.       // 以下是之前放于vuex中用于记录状态
  399.       preCheckedList: [], // 前一次的checkbox
  400.       // 排序的状态
  401.       sort: {
  402.         prop"",
  403.         order"",
  404.         label"",
  405.       },
  406.       // 筛选的状态
  407.       checkBoxFilteredMap: {},
  408.       // input 所有的筛选
  409.       inputFilteredMap: {},
  410.       // columns label及prop对应的键值对
  411.       columnsLabelMap: {}
  412.     };
  413.   },
  414.   watch: {
  415.     // 监听defaultColumn,若这个发生变化,代表传入的默认column变化,即数据表格发生了切换
  416.     defaultColumn() {
  417.       this.initColumns();
  418.     },
  419.     checkedList() {
  420.       // if(this.checkedList.length>0){
  421.       //   this.$emit("selectedColumn",this.checkedList);
  422.       // }
  423.       // 处理当点击checkbox显示的是排序列时,恢复排序列的显示
  424.       let showLabelArray = this.checkboxShowLabel();
  425.       console.log("showLabelArray", showLabelArray);
  426.       // if (value.length !== 0) {
  427.       //   value.map((item) => {
  428.       //     this.handleStatusRevert(item);
  429.       //   });
  430.       this.columns.map((column, index) => {
  431.         this.handleStatusRevert(column, index, showLabelArray);
  432.       });
  433.     },
  434.   },
  435.   created() {
  436.     this.normalizeColumnsLabelMap();
  437.   },
  438.   mounted() {
  439.     if (!this.options.columnsTreeSelect) {
  440.       this.checkedList = this.$props.defaultColumn;
  441.       this.checkBoxOptions = this.$props.totalColumn;
  442.     } else {
  443.       this.checkedList = this.$refs.tree
  444.         .getCheckedNodes()
  445.         .map((item) => item.label);
  446.     }
  447.     // 挂载时将defaultSort属性传给vuex
  448.     this.handleDefaultSort();
  449.   },
  450.   // 动态切换表头的时候闪烁是因为表头重新计算高度导致的,以下方法解决此bug
  451.   beforeUpdate() {
  452.     this.$nextTick(() => {
  453.       //在数据加载完,重新渲染表格
  454.       this.$refs["operateTable"].doLayout();
  455.     });
  456.   },
  457.   methods: {
  458.     //全选字段
  459.     handleCheckAllChange(val){
  460.       this.checkedList = val ? this.checkBoxOptions : [];
  461.       this.isIndeterminate = false;
  462.     },
  463.     //反选
  464.     handleCheckedCitiesChange(value){
  465.       let checkedCount = value.length;
  466.       this.checkAll = checkedCount === this.checkBoxOptions.length;
  467.       this.isIndeterminate = checkedCount > 0 && checkedCount < this.checkBoxOptions.length;
  468.     },
  469.     //初始化字段
  470.     initColumns(flag){
  471.       if(flag){
  472.         this.checkedList = this.$props.defaultSelectedColumn;
  473.       }else{
  474.         this.checkedList = this.$props.defaultColumn;
  475.       }
  476.       this.checkBoxOptions = this.$props.totalColumn;
  477.     },
  478.     // 处理判断checkbox 点击时,显示的是哪个字段名
  479.     checkboxShowLabel() {
  480.       // 判断显示的字段是哪个字段,如果是树形,可能有多个,故更改为数组接收
  481.       let value = [];
  482.       console.log("this.checkedList"this.checkedList);
  483.       if (this.count === 0) {
  484.         this.saveCheckedList(this.checkedList);
  485.         // this.$componentsStore.commit("table/saveCheckedList", this.checkedList);
  486.         this.count++;
  487.       } else {
  488.         if (this.checkedList.length > this.preCheckedList.length) {
  489.           for (let index = 0; index < this.checkedList.length; index++) {
  490.             if (!this.preCheckedList.includes(this.checkedList[index])) {
  491.               value.push(this.checkedList[index]);
  492.             }
  493.             // if (this.checkedList[index] !== this.preCheckedList[index]) {
  494.             //   value = this.checkedList[index];
  495.             // }
  496.           }
  497.         }
  498.         this.saveCheckedList(this.checkedList);
  499.         // this.$componentsStore.commit("table/saveCheckedList", this.checkedList);
  500.       }
  501.       return value;
  502.     },
  503.     // 处理sort\filterd由隐藏变为显示状态的恢复
  504.     handleStatusRevert(column, index, showLabelArray) {
  505.       let compareLabel = column.label;
  506.       if (showLabelArray.includes(compareLabel)) {
  507.         // 如果是有checkbox 筛选的字段,恢复筛选
  508.         let filteredValue =
  509.           this.checkBoxFilteredMap[this.columnsLabelMap[compareLabel]];
  510.         // 如果是有input 筛选的字段,恢复筛选
  511.         let filteredInputValue =
  512.           this.inputFilteredMap[this.columnsLabelMap[compareLabel]];
  513.         this.columns[index].filteredValue = filteredValue;
  514.         this.columns[index].defaultValue = filteredInputValue;
  515.         this.$nextTick(() => {
  516.           this.$refs.operateTable.store.states.columns.map((column) => {
  517.             if (column.filteredValue && column.filteredValue.length) {
  518.               this.$refs.operateTable.store.commit("filterChange", {
  519.                 column,
  520.                 values: column.filteredValue,
  521.                 silenttrue,
  522.               });
  523.             }
  524.           });
  525.         });
  526.       } else {
  527.         this.columns[index].filteredValue = [];
  528.         this.columns[index].defaultValue = "";
  529.       }
  530.       // 如果是有排序的字段,恢复排序
  531.       if (showLabelArray.includes(this.sort.label)) {
  532.         this.$nextTick(() => {
  533.           //在数据加载完,重新渲染表格
  534.           this.isCheckBoxSort = true;
  535.           this.$refs.operateTable.sort(this.sort.propthis.sort.order);
  536.         });
  537.       }
  538.       /**
  539.       // 如果是有checkbox 筛选的字段,恢复筛选
  540.       let filteredValue = this.checkBoxFilteredMap[this.columnsLabelMap[value]];
  541.       // 如果是有input 筛选的字段,恢复筛选
  542.       let filteredInputValue = this.inputFilteredMap[
  543.         this.columnsLabelMap[value]
  544.       ];
  545.       for (let i = 0; i < this.columns.length; i++) {
  546.         if (this.columns[i].label === value) {
  547.           this.columns[i].filteredValue = filteredValue;
  548.           this.columns[i].defaultValue = filteredInputValue;
  549.           this.$nextTick(() => {
  550.             this.$refs.operateTable.store.states.columns.map((column) => {
  551.               if (column.filteredValue && column.filteredValue.length) {
  552.                 console.log("!11");
  553.                 this.$refs.operateTable.store.commit("filterChange", {
  554.                   column,
  555.                   values: column.filteredValue,
  556.                   silent: true,
  557.                 });
  558.               }
  559.             });
  560.           });
  561.         } else {
  562.           this.columns[i].filteredValue = [];
  563.           this.columns[i].defaultValue = "";
  564.         }
  565.       }
  566.       // for (let i = 0; i < this.columns.length; i++) {
  567.       //   if (this.columns[i].label === value) {
  568.       //     this.columns[i].defaultValue = filteredInputValue;
  569.       //   } else {
  570.       //     this.columns[i].defaultValue = "";
  571.       //   }
  572.       // }
  573.       // 如果是有排序的字段,恢复排序
  574.       if (value === this.sort.label) {
  575.         this.$nextTick(() => {
  576.           //在数据加载完,重新渲染表格
  577.           this.isCheckBoxSort = true;
  578.           this.$refs.operateTable.sort(this.sort.prop, this.sort.order);
  579.         });
  580.       }
  581.       */
  582.     },
  583.     // 处理生成columns 的label prop键值对
  584.     normalizeColumnsLabelMap() {
  585.       this.columns.map((column) => {
  586.         this.columnsLabelMap[column.label] = column.prop;
  587.       });
  588.     },
  589.     filterInputMethod(column, inputFilteredMap) {
  590.       console.log("column, inputFilteredMap", column, inputFilteredMap);
  591.       this.inputFilteredMap = inputFilteredMap;
  592.       this.$emit("filterInputMethod", column, inputFilteredMap);
  593.     },
  594.     resetChangeMethod(tableColumn, columnProp) {
  595.       this.$emit("resetChangeMethod", tableColumn, this.inputFilteredMap);
  596.     },
  597.     cellMouseEnter(row, column, cell, event) {
  598.       this.$emit("cell-mouse-enter", row, column, cell, event);
  599.     },
  600.     cellMouseLeave(row, column, cell, event) {
  601.       this.$emit("cell-mouse-leave", row, column, cell, event);
  602.     },
  603.     cellClick(row, column, cell, event) {
  604.       this.$emit("cell-click", row, column, cell, event);
  605.     },
  606.     cellDblclick(row, column, cell, event) {
  607.       this.$emit("cell-dblclick", row, column, cell, event);
  608.     },
  609.     rowClick(row, column, event) {
  610.       this.$emit("row-click", row, column, event);
  611.     },
  612.     rowContextmenu(row, column, event) {
  613.       this.$emit("row-contextmenu", row, column, event);
  614.     },
  615.     rowDblclick(row, column, event) {
  616.       this.$emit("row-dblclick", row, column, event);
  617.     },
  618.     headerClick(column, event) {
  619.       this.$emit("header-click", column, event);
  620.     },
  621.     headerContextmenu(column, event) {
  622.       this.$emit("header-contextmenu", column, event);
  623.     },
  624.     sortChange(sortObj) {
  625.       this.changeSort(sortObj);
  626.       // this.$componentsStore.commit("table/changeSort", sortObj);
  627.       if (!this.isCheckBoxSort) {
  628.         this.$emit("sort-change", sortObj);
  629.       }
  630.       // 还原isCheckBoxSort
  631.       this.isCheckBoxSort = false;
  632.     },
  633.     handleDefaultSort() {
  634.       if (this.options.defaultSort !== undefined) {
  635.         let column = { label"" };
  636.         // for (let index = 0; index < this.columns.length; index++) {
  637.         //   if (this.columns[index].prop === this.options.defaultSort.prop) {
  638.         //     column.label = this.columns[index].label;
  639.         //     break;
  640.         //   }
  641.         // }
  642.         column.label = this.columnsLabelMap[this.options.defaultSort.prop];
  643.         this.changeSort({
  644.           ...this.options.defaultSort,
  645.           column,
  646.         });
  647.       }
  648.     },
  649.     // 点击操作的下拉项目后触发事件
  650.     handleCommand(command) {
  651.       if (command.method) {
  652.         command.method(command.index, command.row, command.label);
  653.       }
  654.     },
  655.     // 点击dropDown传参方法
  656.     composeValue(item, row, index) {
  657.       return {
  658.         label: item.label,
  659.         row: row,
  660.         index: index,
  661.         method: item.method,
  662.       };
  663.     },
  664.     select(selection, row) {
  665.       this.$emit("select", selection, row);
  666.     },
  667.     selectAll(selection) {
  668.       this.$emit("select-all", selection);
  669.     },
  670.     checkboxSelected(selection) {
  671.       this.$emit("selection-change", selection);
  672.     },
  673.     selectable(row, index) {
  674.       let data = true;
  675.       this.$emit("selectable", row, index, (val) => {
  676.         data = val;
  677.       });
  678.       return data;
  679.     },
  680.     getRowKeys(row) {
  681.       let data;
  682.       for (let index = 0; index < this.dataSource.length; index++) {
  683.         if (row === this.dataSource[index]) {
  684.           data = index;
  685.           break;
  686.         }
  687.       }
  688.       // this.dataSource.map((item, index) => {
  689.       //   if (row === item) {
  690.       //     data = index;
  691.       //   }
  692.       // });
  693.       this.$emit("row-key", row, (val) => {
  694.         data = val;
  695.       });
  696.       return data;
  697.     },
  698.     load(tree, treeNode, resolve) {
  699.       this.$emit("load", tree, treeNode, resolve);
  700.     },
  701.     // 记录表格总的筛选状态,用于列显示隐藏时保存checkbox状态
  702.     filterChange(filters) {
  703.       let currKey = Object.keys(filters)[0];
  704.       if (filters[currKey].length === 0) {
  705.         delete this.checkBoxFilteredMap[currKey];
  706.       } else {
  707.         this.checkBoxFilteredMap[currKey] = filters[currKey];
  708.       }
  709.       this.$emit("filter-change", filters);
  710.     },
  711.     checkChange(nodeObj, checkObj) {
  712.       this.checkedList = checkObj.checkedNodes.map((item) => {
  713.         return item.label;
  714.       });
  715.     },
  716.     // 之前写在vuex里的方法
  717.     changeSort(sort) {
  718.       this.sort.prop = sort.prop;
  719.       this.sort.order = sort.order;
  720.       this.sort.label = sort.column.label;
  721.     },
  722.     saveCheckedList(preCheckedList) {
  723.       this.preCheckedList = preCheckedList;
  724.     },
  725.   },
  726. };
  727. </script>
  728. <style>
  729.     .operateTable{
  730.         position: relative;
  731.         width100%;
  732.     }
  733.     .operateTable .column-dropdown{
  734.         position: absolute;
  735.         right0px;
  736.         top: -42px;
  737.         z-index99;
  738.     }
  739.     .caoz_ft_warp{
  740.       text-align: center;
  741.     }
  742.     .caoz_ft_warp .el-input.is-active .el-input__inner.caoz_ft_warp .el-input__inner:focus{
  743.         border-color#9A4B9B;
  744.         outline0;
  745.     }
  746.     .el-checkbox__input.is-checked .el-checkbox__inner,.el-checkbox__input.is-indeterminate .el-checkbox__inner {
  747.         background-color#9a4b9b;
  748.         border-color#9a4b9b;
  749.     }
  750.     .el-checkbox__inner:hover {
  751.         border-color#9A4B9B;
  752.     }
  753.     .el-checkbox__input.is-focus .el-checkbox__inner{
  754.         border-color#9A4B9B;
  755.     }
  756.     .el-checkbox__input.is-checked+.el-checkbox__label {
  757.         color#9A4B9B;
  758.     }
  759.     .checkboxScorll .el-checkbox__input.is-checked + .el-checkbox__label {
  760.         color#666;
  761.     }
  762.     .column-dropdown .el-button{margin-right0 !important;min-width:0;}
  763.     .column-dropdown .el-button:focus.el-button:hover{
  764.         color#9A4B9B;
  765.         border-color#e1c9e1;
  766.         background-color#f5edf5;
  767.     }
  768.     .checkboxScorll {
  769.         max-height300px;
  770.         overflow-y: auto;
  771.     }
  772.     .checkboxScorll .checkbox {
  773.         display: block;
  774.         margin-top10px;
  775.         padding-left20px;
  776.     }
  777. </style>

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

  1. <template>
  2.   <div class="tableView">
  3.     <div class="content">
  4.       <operateTable
  5.         v-loading="loading"
  6.         :dataSource="operateTableData"
  7.         :columns="operateTableColumns"
  8.         :options="operateTableOption"
  9.         :defaultColumn="defaultColumns"
  10.         :totalColumn="totalColumns"
  11.         :defaultSelectedColumn="defaultSelectedColumn"
  12.         @sort-change="sortChange"
  13.         @saveSettingColumns="saveSettingColumns"
  14.       ></operateTable>
  15.     </div>
  16.   </div>
  17. </template>
  18. <script>
  19. import operateTable from "./components/operateTable.vue";
  20. export default {
  21.   name"",
  22.   components: {
  23.     operateTable,
  24.   },
  25.   data() {
  26.     return {
  27.       loadingfalse,
  28.       operateTableData: [
  29.         {
  30.           date"2016-05-02",
  31.           name"王小虎",
  32.           address"上海市普陀区金沙江路 1518 弄",
  33.         },
  34.         {
  35.           date"2016-05-04",
  36.           name"王小虎",
  37.           address"上海市普陀区金沙江路 1517 弄",
  38.         },
  39.         {
  40.           date"2016-05-01",
  41.           name"王小虎",
  42.           address"上海市普陀区金沙江路 1519 弄",
  43.         },
  44.         {
  45.           date"2016-05-03",
  46.           name"王小虎",
  47.           address"上海市普陀区金沙江路 1516 弄",
  48.         },
  49.       ],
  50.       operateTableColumns: [
  51.         {
  52.           prop"action",
  53.           label"操作",
  54.           width100,
  55.           fixedtrue,
  56.           render(h, params) => {
  57.             return h(
  58.               "div",
  59.               {
  60.                 class"operate-group",
  61.               },
  62.               [
  63.                 h(
  64.                   "el-tooltip",
  65.                   {
  66.                     props: {
  67.                       content"处理",
  68.                       placement"bottom",
  69.                       enterablefalse,
  70.                       effect"light",
  71.                     },
  72.                     class"item",
  73.                   },
  74.                   [
  75.                     h("i", {
  76.                       props: {},
  77.                       class"el-icon-edit",
  78.                       on: {
  79.                         click() => {
  80.                           console.log(params.row);
  81.                         },
  82.                       },
  83.                     }),
  84.                   ]
  85.                 ),
  86.               ]
  87.             );
  88.           },
  89.         },
  90.         {
  91.           prop"date",
  92.           label"日期",
  93.           minwidth150,
  94.           sortable"custom",
  95.         },
  96.         {
  97.           prop"name",
  98.           label"姓名",
  99.           minwidth150,
  100.           sortable"custom",
  101.         },
  102.         {
  103.           prop"address",
  104.           label"地址",
  105.           minwidth150,
  106.           sortable"custom",
  107.         },
  108.       ],
  109.       operateTableOption: {
  110.         stripetrue// 是否为斑马纹 table
  111.         highlightCurrentRowtrue// 是否要高亮当前行
  112.         columnsSelecttrue,
  113.         maxHeight300,
  114.       },
  115.       defaultColumns: ["操作""日期""姓名""地址"],
  116.       totalColumns: ["操作""日期""姓名""地址"],
  117.       //所有用户默认勾选的列  用于初始化
  118.       defaultSelectedColumn: [],
  119.     };
  120.   },
  121.   methods: {
  122.     //表头排序
  123.     sortChange(column, prop, order) {
  124.       if (column.order === "ascending") {
  125.         this.orderfield = column.prop;
  126.         this.orderby = "ASC";
  127.       } else if (column.order === "descending") {
  128.         this.orderfield = column.prop;
  129.         this.orderby = "DESC";
  130.       } else {
  131.         this.orderfield = "";
  132.         this.orderby = "";
  133.       }
  134.       //   this.getTabldHandle();
  135.     },
  136.     //保存自定义字段
  137.     saveSettingColumns(data) {
  138.       console.log(data);
  139.     },
  140.   },
  141.   mounted() {},
  142. };
  143. </script>
  144. <style>
  145. .tableView {
  146.   width100%;
  147.   height100%;
  148. }
  149. .content {
  150.   padding60px;
  151. }
  152. .disableIcon {
  153.   color#c0c4cc;
  154.   cursor: not-allowed;
  155. }
  156. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/353368
推荐阅读
  

闽ICP备14008679号