The el-table header and content in elementUI are all displayed in one line

There is a requirement in the project that el-table is required to display data, and there is a requirement that the line cannot be changed. The table header cannot wrap, and the content in the table cannot wrap either.

The page written by a colleague uses vue3, and an event is customized to dynamically change the parameters of each column. I transferred it to vue2 and it was completely useless. It can only be realized by finding information on the Internet.

The table is obtained through the interface, which separates the header title from the table content.

The basic idea is: the content of the table is limited to no line breaks, and no abbreviations are used.

First start from the table header, there is a render-header in el-table-column

    // 表头部重新渲染
		renderHeader(h, { column, $index }) {
			// 新建一个 span
			let span = document.createElement('span');
			// 设置表头名称
			span.innerText = column.label;
			// 临时插入 document
			document.body.appendChild(span);
			// 重点:获取 span 最小宽度,设置当前列,注意这里加了 20,字段较多时还是有挤压,且渲染后的 div 内左右 padding 都是 10,所以 +20 。(可能还有边距/边框等值,需要根据实际情况加上)
			column.minWidth = (span.getBoundingClientRect().width) + 40;
            this.headerLableWidth[column.property] = column.minWidth;
			// 移除 document 中临时的 span
			document.body.removeChild(span);
			return h('span', column.label);
		},

There are these title text information in the column. Create a span tag, add it to the document flow, and then get its width. In order to add more width, you can add some additional values. An extra 40 width is added to the code. Sets the minimum width for the header.

Record the minimum width of this column. When the width of the table content is dynamically set, at least the width of the header must be given. Otherwise, the width of the header will become 0 because there is no content.

    flexColumnWidth(str, arr1, flag = 'max'){
      // str为该列的字段名(传字符串);tableData为该表格的数据源(传变量);
      // flag为可选值,可不传该参数,传参时可选'max'或'equal',默认为'max'
      // flag为'max'则设置列宽适配该列中最长的内容,flag为'equal'则设置列宽适配该列中第一行内容的长度。
      str = str + ''
      let columnContent = ''
      if (!arr1 || !arr1.length || arr1.length === 0 || arr1 === undefined) {
        return
      }
      if (!str || !str.length || str.length === 0 || str === undefined) {
        return
      }
      if (flag === 'equal') {
        // 获取该列中第一个不为空的数据(内容)
        for (let i = 0; i < arr1.length; i++) {
          if (arr1[i][str].length > 0) {
            // console.log('该列数据[0]:', arr1[0][str])
            columnContent = arr1[i][str]
            break
          }
        }
      } else {
        // 获取该列中最长的数据(内容)
        let index = 0
        for (let i = 0; i < arr1.length; i++) {
          if (arr1[i][str] === null) {
            return
          }
          const now_temp = arr1[i][str] + ''
          const max_temp = arr1[index][str] + ''
          if (now_temp.length > max_temp.length) {
            index = i
          }
        }
        columnContent = arr1[index][str]
      }
      // console.log('该列数据[i]:', columnContent)
      // 以下分配的单位长度可根据实际需求进行调整
      let flexWidth = 0
      for (const char of String(columnContent)) {
        if ((char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z')) {
          // 如果是英文字符,为字符分配8个单位宽度
          flexWidth += 10
        } else if (char >= '\u4e00' && char <= '\u9fa5') {
          // 如果是中文字符,为字符分配15个单位宽度
          flexWidth += 18
        } else {
          // 其他种类字符,为字符分配8个单位宽度
          flexWidth += 10
        }
      }
      if (flexWidth < this.headerLableWidth[str]) {
        // 设置最小宽度
        flexWidth = this.headerLableWidth[str]
      }
      // if (flexWidth > 250) {
      //   // 设置最大宽度
      //   flexWidth = 250
      // }
      // console.log(flexWidth)
      return flexWidth + 'px'
    }
  }

The width in the el-table-column tag is replaced by a function method.

The complete el-table is as follows

        <el-table 
          :ref='tableRef'
          :data="certRecordInfos"
          border
          :fit="true"
          style="width: 100%">
          <el-table-column
            align="center"
            :render-header="renderHeader"
            :width="flexColumnWidth(item.key,certRecordInfos)"
            :key="item.key" 
            :prop="item.key"  
            :label="item.value" >
          </el-table-column>
        </el-table>

Because the minimum width of the table header needs to be obtained first, the table header needs to be loaded first to ensure that the width can be set correctly when the table content is loaded later.

In watch, observe these two arrays, and refresh the table when changes are found

    certHeaderList: {
      deep: true,
      handler: function (val) {
        this.$nextTick(() => {
          this.$refs[`${this.tableRef}`].doLayout();
        })
      }
    },
    certRecordInfos: {
      deep: true,
      handler: function (val) {
        this.$nextTick(() => {
          this.$refs[this.tableRef].doLayout();
        })
      }
    }
        this.certHeaderList.splice(0)
        this.certRecordInfos.splice(0)
        const resultHeader = val[0].header
        resultHeader.forEach((header)=>{
          let map = {key:header.columnName,value:header.columnDesc};
          this.certHeaderList.push(map);
        });
        setTimeout(() => {
          const resultList = val[0].list
          this.certRecordInfos.push(...resultList)
        }, 1000);

To achieve the effect, it must be ensured that the minimum width of each column header of the table has been obtained. And document it with headerLableWidth.

In addition, you need to set up the content of the table to ensure that the content will not wrap and use abbreviated symbols.

/deep/ .el-table th, .el-table td {
  white-space: nowrap;
}

/deep/ .el-table .cell {
  display: inline-block;
  white-space: nowrap;
  width: auto;
  overflow: auto;
}

/deep/ .el-table .el-table__body-wrapper {
  overflow-x: auto;
}

Guess you like

Origin blog.csdn.net/GhostPaints/article/details/129735041