ant-design-vue a-table 表头固定后和内容不对齐的问题

  • 前言
  • padding, border 和 margin
  • 固定内容列的宽度
  • 完整的columns和HTML内容(不太完整,没敢全放)
  • 笔记
  • 问题


前言

最近在项目中使用ant-design-vue,在做表格的时候需要固定表头,但是发现列对不齐,相信使用过的同学都遇到过这个问题。

网上各种查找,还是找不到解决办法,在这里强调一下,官方文档说需要指定column的width属性,否则列头和表头可能不对齐。

怎么改变Ant Design Vue 中 DatePick组件中弹出框位置 ant design vue loading_bc


但是我在使用时发现,不仅要设置width,表头列的宽度内容列的宽度和还需要相等才行。

padding, border 和 margin

a-table组件,thtd 自带有默认的padding值,在这里我怕影响展示效果,就给换成了自己的。这里注意thtdbox-sizeing属性的值是border-box,也就是说宽度和高度影响了边框盒,就算添加了padding和border不影响总的宽度。

/* 表 固定 单元格设置 官网推荐 內容單元格設置 消除单元格边距 */
.table-people-sign-in-content .ant-table td {
	/* 没用了*/
  white-space: nowrap;
  padding: 0;
}
/* 表頭 cell単元格設置 */
.table-people-sign-in-content .ant-table-thead > tr > th {
  padding-left: 8px;
  padding-right: 0px;
  border: 0;
  font-weight: 700;
}

我这里把组件原来的thtd的样式给覆盖了,添加了自己的padding,是为了我能自己控制效果。
另外,white-space: nowrap在这里没用了,原因看下面。

固定内容列的宽度

怎么固定内容列的宽度呢,表头固定后,td默认是按内容大小自适应的,这也是造成不对齐的原因,我的做法是在每一个td中嵌套一个div

<template solt:"customDiv slot-scope="data">
     <div class="row-cell-div" :style="tdDivStyle">
        <span>{{data}}</span>
      </div>
  </template>

如下代码 column中该列的值就要添加scopedSlots属性,"row-text-view"就相当于 vue中插槽的name特性。

let columns= [{
          dataIndex: 'name',
          title: 'title',//表头显示的内容
          width: this.colsWidth[i],//这个用来设置表头列宽
          //自定义作用域插槽
          scopedSlots: { customRender: "row-text-view" }
        },
        ...
   ];

这样就可以在这个div中加入自己的元素,比如在这里我就加了个span标签用来显示data,那这个data是什么呢?
我们看看 table数据源的定义:

let data = [{
		key: 'uniqe key',
		name: 'zhangsan',
		...}
		...
	};

column中的dataIndex的值是'name',而name对应data中的name属性,所以这里data就是'zhangsan'key用来区分数据的唯一性,就像数据库中的id一样
注意columns中的每一列的dataIndex,对应data中的每个对象的一个属性。
至此 white-space: nowrap确实没用了,因为都自己写了。

完整的columns和HTML内容(不太完整,没敢全放)

实际上,项目中有很多列,可能每列的样式还不一样,我是这样做的:

let columns = [];
 let i = 0;
 for (; i < colTitle.length; i++) {
        const title = colTitle[i];
        let col = {
          index: i,//标记当前列索引,
          slotType: "text",//当前列显示类型
          dataIndex: title,//我懒了直接用了title值
          title: title,
          width: this.colsWidth[i],//列宽度
          //列中自定义样式对象
          tdDivStyle: {
            width: this.colsWidth[i] + "px"//每一列的宽度内联样式
          },
          //自定义作用域插槽
          scopedSlots: { customRender: "row-text-view" + i }//每一列的插槽
        };
        ...
        columns.push(col);
     }

this.colsWidth[i]用到了,至于colsWidth是啥就不用说了吧,这里还添加了index、soltType和tdDivStyle

  • index 用来记录列索引 当然也可以在v-for中使用(value, index) in …;
  • soltType 用来区分插槽内容,比如文字、图片、或者其他 只要能放得下;
  • tdDivStyle 用来记录当前列td里面div的样式,这里仅仅设置了宽度;
    html是这个样子:
<!-- 遍历语法 从columns中获取scopedSlots的值 -->
      <template v-for="col in columns" :slot="col.scopedSlots.customRender" slot-scope="data">
        <!-- 自定義 文字插值-->
        <template v-if="col.slotType === 'text'">
          <div class="row-cell-div" :style="col.tdDivStyle" :key="col.index">
            <span>{{data}}</span>
          </div>
        </template>
       <!--...这里还有其他的-->
      </template>

外层是一个a-table组件。
基本上一看就懂,class="row-cell-div"可以全局设置样式,有特别的特别对待。

笔记

a-table的scroll="{x:tableXWidth,y:height} 这里的height仅仅是行内容可以滑动的高,不包括表头和分页组件。
a-table适应浏览器高度可以设置height="calc(100vh - abcpx)",abc是除内容外的高度,如果计算的准的话,浏览器的垂直滑动条也会消失。

问题

这个方式浏览器不缩放还行,浏览器缩放还会导致不对齐,希望看到这篇文章的老铁们不吝赐教,多多指正。