前言
最近写vue的项目,接触到了一个问题,就是el-table中的max-height只在设置为px时滚动才生效,而为100%时滚动未生效,而height属性设置为100%则正常,因此阅读了下el-table的源码,解决了下这个问题。
max-height不滚动原因
我们先来看下dom结构是怎样的。
先将max-height设置为固定px值250px,可以看到el-table__body-wrapper盒子设置了一个max-height,下级的table为自个的高度,那在这种情况下滚动正常。
将max-height设置为100%后,可以看到el-table__body-wrapper盒子的max-height属性未设置,变成了下级table的高度,滚动失效。
阅读源码,可以找到el-table__body-wrapper的style样式来自bodyHeight
bodyHeight() {
const { headerHeight = 0, bodyHeight, footerHeight = 0} = this.layout;
if (this.height) {
return {
height: bodyHeight ? bodyHeight + 'px' : ''
};
} else if (this.maxHeight) {
const maxHeight = parseHeight(this.maxHeight);
if (typeof maxHeight === 'number') {
return {
'max-height': (maxHeight - footerHeight - (this.showHeader ? headerHeight : 0)) + 'px'
};
}
}
return {};
}
// parseHeight
function parseHeight(height) {
if (typeof height === 'number') {
return height;
}
if (typeof height === 'string') {
if (/^\d+(?:px)?$/.test(height)) {
return parseInt(height, 10);
} else {
return height;
}
}
return null;
}
源码中可以看到parseHeight函数,当传入值为字符串时会正则匹配/^\d+(?:px)?$/,那当我们传入的为100%时,这边就匹配不到,啥也没返回,因此就有了上面的可以看到的现象el-table__body-wrapper盒子的max-height属性未设置,自然就不会有滚动效果了。
解决方案
知道了原因,那来解决下这个问题。
可以看到问题出在了bodyHeight,那我们要做的就是重写bodyHeight这个计算方法,这边可以用到vue的extends方法。创建一个MyTable.vue文件,先继承el-table
import { Table } from "element-ui";
export default {
extends: Table,
};
我们对bodyHeight函数进行改造,当maxHeight字段正则匹配为百分比时,进行calc重新计算max-height的高度
import { Table } from "element-ui";
import { parseHeight } from "element-ui/packages/table/src/util.js";
export default {
extends: Table,
computed: {
bodyHeight() {
const { headerHeight = 0, bodyHeight, footerHeight = 0 } = this.layout;
if (this.height) {
return {
height: bodyHeight ? bodyHeight + "px" : "",
};
} else if (this.maxHeight) {
const maxHeight = parseHeight(this.maxHeight);
if (typeof maxHeight === "number") {
return {
"max-height":
maxHeight -
footerHeight -
(this.showHeader ? headerHeight : 0) +
"px",
};
} else if (maxHeight.match(/\d+%/g)) {
return {
"max-height": `calc(${maxHeight} - ${
footerHeight + this.showHeader ? headerHeight : 0
}px)`,
};
}
}
return {};
},
},
};
查看效果时,el-table__body-wrapper盒子有了max-height属性,可滚动还是没有出现,分析dom结构,可以看到问题就出在父盒子el-table的高度也为max-height:100%,因此子盒子的max-height:100%并不会起作用。
解决办法可以通过flex来解决,给父盒子添加display:flex;
滚动条出现,但布局乱了,我们再解决下布局问题就可以了。
给表头el-table__header-wrapper盒子添加flex-shrink: 0;,表格el-table__body-wrapper盒子添加flex-grow: 1;
滚动条出现,问题解决。
最终重写的MyTable代码:
<script>
import { Table } from "element-ui";
import { parseHeight } from "element-ui/packages/table/src/util.js";
export default {
extends: Table,
computed: {
bodyHeight() {
const { headerHeight = 0, bodyHeight, footerHeight = 0 } = this.layout;
if (this.height) {
return {
height: bodyHeight ? bodyHeight + "px" : "",
};
} else if (this.maxHeight) {
const maxHeight = parseHeight(this.maxHeight);
if (typeof maxHeight === "number") {
return {
"max-height":
maxHeight -
footerHeight -
(this.showHeader ? headerHeight : 0) +
"px",
};
} else if (maxHeight.match(/\d+%/g)) {
return {
"max-height": `calc(${maxHeight} - ${
footerHeight + this.showHeader ? headerHeight : 0
}px)`,
};
}
}
return {};
},
},
};
</script>
<style scoped>
.el-table {
display: flex;
flex-direction: column;
}
.el-table >>> .el-table__header-wrapper {
flex-shrink: 0;
}
.el-table >>> .el-table__body-wrapper {
flex-grow: 1;
}
</style>
// 调用
<my-table :data="tableData" max-height="100%" border style="width: 100%">
<el-table-column prop="date" label="日期" width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</my-table>