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>
相关文章:
Vue+Element Ui实现el-table自定义表头下拉选择表头筛选
用vueelement ui开发管理系统时,使用el-table做表格,当表格列过多的时候,想要做成可选表头的,实现表格列的筛选显示,效果如下: 代码文件结构: 废话不多说,直接上代码: 第…...
使用Java连接MongoDB (6.0.12) 报错
报错: Exception in thread "main" com.mongodb.MongoCommandException: Command failed with error 352: Unsupported OP_QUERY command: create. 上图中“The client driver may require an upgrade”说明了“客户端驱动需要进行升级”,解…...
数学建模day16-预测模型
本讲首先将介绍灰色预测模型,然后将简要介绍神经网络在数据预测中的应用,在本讲的最 后,我将谈谈清风大佬对于数据预测的一些看法。 注:本文源于数学建模学习交流相关公众号观看学习视频后所作 目录 灰色系统 GM(1,1)…...
Vue3响应式系统(一)
一、副作用函数。 副作用函数指的是会产生副作用的函数。例如:effect函数会直接或间接影响其他函数的执行,这时我们便说effect函数产生了副作用。 function effect(){document.body.innerText hello vue3 } 再例如: //全局变量let val 2f…...
MStart | MStart开发与学习
MStart | MStart开发与学习 1.学习 1.MStart |开机LOG显示异常排查及调整...
GoZero微服务个人探索之路(一)Etcd:context deadline exceeded原因探究及解决
产生错误原因就是与etcd交互时候需要指定: 证书文件的路径 客户端证书文件的路径 客户端密钥文件的路径 (同时这貌似是强制默认就需要指定了) 但我们怎么知道这三个文件路径呢,如下方法 1. 找到etcd的配置文件,里…...
C语言从入门到实战——结构体与位段
结构体与位段 前言一、结构体类型的声明1.1 结构体1.1.1 结构的声明1.1.2 结构体变量的创建和初始化 1.2 结构的特殊声明1.3 结构的自引用 二、 结构体内存对齐2.1 对齐规则2.2 为什么存在内存对齐2.3 修改默认对齐数 三、结构体传参四、 结构体实现位段4.1 什么是位段4.2 位段…...
java如何修改windows计算机本地日期和时间?
本文教程,主要介绍,在java中如何修改windows计算机本地日期和时间。 目录 一、程序代码 二、运行结果 一、程序代码 package com;import java.io.IOException;/**** Roc-xb*/ public class ChangeSystemDate {public static void main(String[] args)…...
flink中的row类型详解
在Apache Flink中,Row 是一个通用的数据结构,用于表示一行数据。它是 Flink Table API 和 Flink DataSet API 中的基本数据类型之一。Row 可以看作是一个类似于元组的结构,其中包含按顺序排列的字段。 Row 的字段可以是各种基本数据类型&…...
漏洞复现-Yearning front 任意文件读取漏洞(附漏洞检测脚本)
免责声明 文章中涉及的漏洞均已修复,敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…...
K8S中SC、PV、PVC的理解
存储类(StorageClass)定义了持久卷声明(PersistentVolumeClaim)所需的属性和行为,而持久卷(PersistentVolume)是实际的存储资源,持久卷声明(PersistentVolumeClaim&#…...
Agisoft Metashape 基于影像的外部点云着色
Agisoft Metashape 基于影像的外部点云着色 文章目录 Agisoft Metashape 基于影像的外部点云着色前言一、添加照片二、对齐照片三、导入外部点云四、为点云着色五、导出彩色点云前言 本教程介绍了在Agisoft Metashape Professional中,将照片中的真实颜色应用于从不同源获取的…...
图解结算平台:准确高效给商户结款
这是《百图解码支付系统设计与实现》专栏系列文章中的第(4)篇。 本章主要讲清楚支付系统中商户结算涉及的基本概念,产品架构、系统架构,以及一些核心的流程和相关领域模型、状态机设计等。 1. 前言 收单结算是支付系统最重要的子…...
修改和调试 onnx 模型
1. onnx 底层实现原理 1.1 onnx 的存储格式 ONNX 在底层是用 Protobuf 定义的。Protobuf,全称 Protocol Buffer,是 Google 提出的一套表示和序列化数据的机制。使用 Protobuf 时,用户需要先写一份数据定义文件,再根据这份定义文…...
不同整数的最少数目和单词直接最短距离
写是为了更好的思考,坚持写作,力争更好的思考。 今天分享两个关于“最小、最短”的算法题,废话少说,show me your code! 一、不同整数的最少数目 给你一个整数数组arr和一个整数k。现需要从数组中恰好移除k个元素&…...
【Microsoft Edge】版本 109.0.1518.55 (正式版本) (64 位) 更新失败解决方案
Microsoft Edge 版本号 109.0.1518.55(正式版本)(64位) 更新直接报错 检查更新时出错: 无法创建该组件(错误代码 3: 0x80040154 – system level) 问题出现之前 之前电脑日常硬盘百分百(删文件和移动文件都慢得像…...
深度学习笔记(四)——使用TF2构建基础网络的常用函数+简单ML分类实现
文中程序以Tensorflow-2.6.0为例 部分概念包含笔者个人理解,如有遗漏或错误,欢迎评论或私信指正。 截图和程序部分引用自北京大学机器学习公开课 TF2基础常用函数 1、张量处理类 强制数据类型转换: a1 tf.constant([1,2,3], dtypetf.floa…...
大模型学习篇(一):初识大模型
目录 一、大模型的定义 二、大模型的基本原理与特点 三、大模型的分类 四、大模型的相关落地产品 五、总结 一、大模型的定义 大模型是指具有数千万甚至数亿参数的深度学习模型。大模型具有以下特点: 参数规模庞大:大模型的一个关键特征是其包含了…...
uni-app的学习【第二节】
四 路由配置及页面跳转 (1)路由配置 uni-app页面路由全部交给框架统一管理,需要在pages.json里配置每个路由页面的路径以及页面样式(类似小程序在app.json中配置页面路由) 接着第一节的文件,在pages里面新建三个页面 将之前的首页替换为下面的内容,其他页面如下图 然…...
matlab行操作快?还是列操作快?
在MATLAB中,通常情况下,对矩阵的列进行操作比对行进行操作更有效率。这是因为MATLAB中内存是按列存储的,因此按列访问数据会更加连续,从而提高访问速度。 一、实例代码 以下是一个简单的测试代码, % 测试矩阵大小 ma…...
RVC与ElevenLabs对比:开源可控性vs商业易用性深度分析
RVC与ElevenLabs对比:开源可控性vs商业易用性深度分析 想用AI克隆自己的声音,或者让喜欢的角色开口唱歌?现在市面上有两大主流选择:开源的RVC和商业化的ElevenLabs。一个免费但需要折腾,一个付费但开箱即用。到底哪个…...
煤矸石自动分离机设计【论文+CAD图纸】
煤矸石作为煤炭开采与洗选过程中产生的固体废弃物,其成分复杂、粒度分布不均,传统人工分选效率低且精度难以保证。煤矸石自动分离机的设计以机械结构优化与物料特性分析为核心,通过多级筛分与智能识别技术的结合,实现煤矸石与煤炭…...
OpenClaw模型微调:优化千问3.5-35B-A3B-FP8在特定任务的表现
OpenClaw模型微调:优化千问3.5-35B-A3B-FP8在特定任务的表现 1. 为什么需要微调千问模型? 当我第一次尝试用OpenClaw自动化处理财务报告时,发现千问3.5-35B-A3B-FP8虽然能理解基本指令,但在处理表格数据提取和金额计算时频繁出错…...
企业 Agent 流程上线后,如何实现持续优化与迭代?——2026年企业级智能体长效运营全景指南
进入2026年,企业级智能体(Enterprise AI Agent)已从早期的“实验性POC”全面转向“大规模生产部署”。然而,行业调研显示,超过60%的Agent流程在上线初期表现惊艳,却在运行3-6个月后因业务环境变化、知识库过…...
Linux端口占用排查:工具与实战技巧
1. 网络端口占用排查的必要性遇到"Address already in use"错误提示时,每个Linux系统管理员都会心头一紧。这种端口冲突问题不仅影响服务启动,还可能导致关键业务中断。我刚入行时就曾因为Nginx和Apache争抢80端口,导致公司官网瘫痪…...
MAX17043电量计驱动开发:嵌入式电池管理实战指南
1. MAX17043 电量计库深度解析:面向嵌入式工程师的底层驱动开发指南1.1 芯片级功能定位与工程价值MAX17043 是 Maxim Integrated(现为 Analog Devices)推出的高精度单节锂离子/锂聚合物电池电量计 IC,采用 12 引脚 TDFN 封装&…...
苹果内购Java后端避坑指南:收据验证、状态码处理和防重复消费实战
苹果内购Java后端深度防御指南:从收据验收到分布式幂等设计 当你的应用内购收入突然出现异常波动,或是用户投诉被重复扣款时,背后往往隐藏着苹果内购接口的"暗礁"。作为经历过百万级内购交易的老兵,我想分享几个真实生产…...
机器人运动规划:轨迹规划算法核心综述
前言在机器人和自动驾驶领域,“路径规划”(Path Planning)和“轨迹规划”(Trajectory Planning)是两个常被提及的概念。路径规划:解决“怎么走”的问题,关注空间几何路径,不含时间属…...
所有下载都一定要直接从个人服务器直接下载--------因为个人宽带的上传速度一点也不慢
可以看到居然速度高达10M/S如果你直接从云服务器下载速度就非常慢:这就是1M的宽带,所以很慢。所以如果是下载apk文件,一定要从自己的服务器直接下载:就是带10001端口号的个人服务器。...
GHelper终极指南:如何用开源工具彻底掌控华硕笔记本性能
GHelper终极指南:如何用开源工具彻底掌控华硕笔记本性能 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, …...
