目录前言colgroup 和 col核心实现一些常量/变量定义初始化表头列表 initColumns处理含有固定宽度和最小宽的列获取各列宽度,并组成一个数组 getWidthList
如果你使用过类似于 ElementUI 的组件库,一定对如下的 api 属性不眼生,例如:
<!-- Element UI -->
<el-table-column prop="date" label="日期" min-width="150"></el-table-column>
<el-table-column prop="name" label="姓名" width="200"></el-table-column>
<el-table-column prop="province" label="省份" width="200"></el-table-column>
<!-- and-design for Vue -->
cols: [
{ title: '日期',dataindex: 'date',key: 'date', minWidth: 150 },
{ title: '姓名',dataIndex: 'name',key: 'name', width: 200 },
{ title: '省份',dataIndex: 'province',key: 'province', width: 200 },
],
上面的例子中,Table 组件支持自定义最小宽度min-width
和固定宽度width
,如果不设置,则默认填充剩余宽度。
如果你打算自己手动实现一个 Table 组件,并且对支持定义列宽属性的实现毫无头绪,那这篇文章大概率可以帮你梳理一些逻辑和核心方法的实现(vue3)
注:这也许不是最佳的实现方案。
准备工作:
这里假定使用的是类似于and-design for vue
的属性传值方式,即列的属性配置是通过额外的数组对象传入的。
除了title
-列表头名,key
-列值对应的键外,还有这篇文章涉及到的最小宽度minWidth
和固定宽度width
,并通过组件属性cols
传入。
这里需要用到<colgroup>
和<col>
标签,以便更好的去控制每列的属性信息,两个标签均支持传入width
属性控制列宽度,不同的是,<col>
控制的是单列的宽度,而<colgroup>
可以控制所包含在内的。
除此之外,这两个标签还有如下注意事项:
colgroup
需在 table 标签中col
需在 colgroup 标签中,且只能包含 标签col
必须含有结束标签根据我们的需求,我们需要单独控制每一列的宽度展示,并在浏览器宽度变化时实时的重新计算并且重新渲染列。
大致的功能如下:
width
的列,宽度固定,不随浏览器宽度变化而变化minWidth
的列,在大于设定值时,自动填充 table 剩余宽度,小于设定值时,固定该宽度width
和minWidth
的列,自动填充 table 剩余宽度最终实现如下渲染效果:
<template>
<colgroup>
<col
v-for="(item, index) in columns"
:key="`table-tr-${index}`"
:name="`table_tr_${index}`"
:width="`${item.width}px`"
/>
</colgroup>
</template>
在 Table 组件初始化的时候,需要定义一些变量以供后续方法中使用,具体如下:
const bpTable = ref(null);
const columns = ref([]);
const _table_width = ref("");
let _remainder_col = 0;
let _fixed_width = 0;
let _min_width_list = [];
let _col_width_list = [];
const _min_column_width = 80;
在表格整体渲染结束,能获取 table 实际宽度后,需要执行表头列表初始化,对传入的props
中的cols
进行处理,计算实际每一列需要width
值。
const initColumns = () => {
const el = bpTable.value;
const { cols } = props;
_fixed_width = 0;
_remainder_col = cols.length;
_min_width_list = [];
// 1. 处理含有固定宽度和最小宽的列
// 2. 获取各列宽度,并组成一个数组
// 计算需要自适应的列宽度
// 3. 输出 columns
}
如果含有自定义的宽和最小宽,则需要单独处理这些列,使其不参与剩余宽度自适应当中,同时对应的自适应列的数量也要相应的减去,处理逻辑如下:
for (let i = 0; i < cols.length; i++) {
const { width, minWidth } = cols[i];
if (width) {
_fixed_width += Number(width);
_remainder_col--;
}
minWidth && _min_width_list.push(minWidth)
}
这个方法目的返回一个数组,包含各列的宽度值,最后匹配到columns
中。 为了不出现列宽过于太小而把内容挤掉的情况,需要判断最小值不能小于设定的80px
。
function getWidthList() {
const { cols } = props;
let width_list = [];
let adapt_width = getAdaptWidth();
if (_min_width_list.length) {
_min_width_list.map((item, index) => {
if (adapt_width > item) {
_fixed_width += item;
_remainder_col--;
_min_width_list.splice(index, 1);
adapt_width = getAdaptWidth();
}
});
}
for (let i = 0; i < cols.length; i++) {
const { width, minWidth } = cols[i];
// 设置成固定宽度
if (width) { width_list.push(width); continue; }
// 是否设置成最小宽度:当含有最小宽度属性并且最小宽度大于计算得出的最大列宽
const hasMinWidth = minWidth && minWidth > adapt_width;
if (hasMinWidth) { width_list.push(minWidth); continue; }
// 如果没有定义宽度和最小宽,则设置成自适应宽度或者最小预设宽度
width_list.push(adapt_width < _min_column_width ? _min_column_width : adapt_width);
}
return width_list;
}
在表格整体渲染结束,能获取 table 实际宽度后,需要计算允许列自适应的宽度有多少,如果所有列都没有设置宽度值,这时候自适应的列宽即为 table 的实际宽度,列宽平均分布就行了。
function getAdaptWidth() {
let width = (_table_width.value - _fixed_width) / _remainder_col;
return Number(width).toFixed(2);
}
```
#### 完整代码
```javascript
function getWidthList() {
const { cols } = props;
let width_list = [];
let adapt_width = getAdaptWidth();
if (_min_width_list.length) {
_min_width_list.map((item, index) => {
if (adapt_width > item) {
_fixed_width += item;
_remainder_col--;
_min_width_list.splice(index, 1);
adapt_width = getAdaptWidth();
}
});
}
for (let i = 0; i < cols.length; i++) {
const { width, minWidth } = cols[i];
// 设置成固定宽度
if (width) { width_list.push(width); continue; }
// 是否设置成最小宽度:当含有最小宽度属性并且最小宽度大于计算得出的最大列宽
const hasMinWidth = minWidth && minWidth > adapt_width;
if (hasMinWidth) { width_list.push(minWidth); continue; }
// 如果没有定义宽度和最小宽,则设置成自适应宽度或者最小预设宽度
width_list.push(adapt_width < _min_column_width ? _min_column_width : adapt_width);
}
return width_list;
}
触发initColumns
的时机有三个
watch(() => props.cols, () => { initColumns() });
onMounted(() => {
nextTick(() => {
initColumns();
on(window, 'resize', throttle(() => initColumns(), 400));
});
});
onBeforeUnmount(() => off(window, 'resize', () => initColumns()));
到此这篇关于vue.js Table 组件自定义列宽实现核心方法的文章就介绍到这了,更多相关vue.js Table 组件自定义内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: vue.js Table 组件自定义列宽实现核心方法
本文链接: https://www.lsjlt.com/news/165139.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0