当前位置: 首页 > article >正文

vue3+element-plus中的el-table表头和el-table-column内容全部一行显示完整(hook函数)

hook函数封装

export const useTableColumnWidth = _this => {
  const { refTable } = _this
  const columnWidthObj = ref()

  const getTableColumnWidth = cb => {
    nextTick(() => {
      columnWidthObj.value = {}
      // 获取行rows
      const tableEle = refTable?.refBaseTable?.$el
      if (!tableEle) return
      const rows = tableEle.querySelectorAll(
        '.el-table__body-wrapper .el-table__row'
      )
      if (!rows.length) return
      // 获取props
      const hideRows = tableEle.querySelectorAll('.hidden-columns div')
      // 每一行的列总数
      const cells = rows[0].cells
      Array.from(cells).forEach((cell, i) => {
        // 初始化内容宽度
        let maxVal = 0
        // 获取prop属性
        const prop = hideRows[i].getAttribute('data-prop')
        if (!prop) return
        // 计算一列内容最宽的宽度
        Array.from(rows).forEach(row => {
          // 将表格列的元素转化为行内元素,最大限度的保持一行显示,从而计算内容的宽度
          const cellsEle = row.cells[i]
          cellsEle.style.display = 'inline-block'
          cellsEle.style.width = '100vw'
          const cellEle = cellsEle.querySelector('.cell')
          // 比较一列最长的宽度数值
          cellEle.style.display = 'inline-block'
          maxVal = Math.max(
            cellEle.getBoundingClientRect().width + 1, // 必须用这个方法,否则小数点会被忽略
            maxVal
          )
          // 将表格列的元素恢复为表格布局
          cellsEle.style.display = 'table-cell'
          cellsEle.style.width = 'auto'
          cellEle.style.display = 'block'
        })
        columnWidthObj.value[prop] = Math.ceil(maxVal)
      })
      cb(columnWidthObj.value)
      // console.log('this.columnWidthObj', columnWidthObj.value)
    })
  }

  return {
    columnWidthObj,
    getTableColumnWidth
  }
}

自定义组件封装

  1. BaseTable
<template>
  <el-table
    ref="refBaseTable"
    class="dy-list-table"
    element-loading-background="rgba(0, 0, 0, 0.8)"
    :stripe="stripe"
    border
    :height="height"
    :="$attrs"
  >
    <slot />
  </el-table>
</template>

<script setup>
defineProps({
  height: {
    type: String,
    default: '100%'
  },
  stripe: {
    type: Boolean,
    default: true
  }
})

const refBaseTable = ref(null)

defineExpose({
  refBaseTable
})
</script>
  1. TableColumn
<template>
  <el-table-column
    v-if="hasDefaultSlot"
    :min-width="getMinWidth()"
    :width="cWidth"
    :data-prop="dataProp"
    :="$attrs"
  >
    <template #default="scope">
      <slot v-bind="scope" />
    </template>
  </el-table-column>
  <el-table-column
    v-else
    :min-width="getMinWidth()"
    :width="cWidth"
    :data-prop="dataProp"
    :="$attrs"
  />
</template>

<script setup>
const props = defineProps({
  dataProp: {
    type: String,
    default: ''
  },
  width: {
    type: [String, Number],
    default: ''
  }
})

const $attrs = useAttrs()
const slots = useSlots()
const cWidth = ref(props.width)

const hasDefaultSlot = computed(() => !!slots.default)

const getMinWidth = () => {
  // 表头宽度
  const minWidth = g_utils.calcTextWidth($attrs.label)
  // 表头宽度与展示内容宽度对比出最大值
  let actualWidth = $attrs['column-width']
    ? Math.max(minWidth, $attrs['column-width'])
    : minWidth
  if ($attrs['show-overflow-tooltip'] !== undefined) {
    actualWidth += 2
  }
  if ($attrs['column-type'] === 'width') {
    cWidth.value = actualWidth + 10 // 10为随机数
    return ''
  } else {
    if ($attrs.sortable !== undefined) actualWidth += 24
    return actualWidth
  }
}
</script>
  1. 动态计算文本的宽度
export const calcTextWidth = (
  str = '',
  style = {
    fontSize: '16px',
    fontWeight: 'bold'
  }
) => {
  // 新建一个 span
  const span = document.createElement('span')
  // 设置表头名称
  span.innerText = str
  // 设置表头样式
  span.style.fontSize = style.fontSize
  span.style.fontWeight = style.fontWeight
  // 临时插入 document
  document.body.appendChild(span)
  // 重点:获取 span 最小宽度,设置当前列,注意这里加了 20,字段较多时还是有挤压,且渲染后的 div 内左右 padding 都是 10,所以 +20 。(可能还有边距/边框等值,需要根据实际情况加上)
  const width = span.getBoundingClientRect().width + 25
  // 移除 document 中临时的 span
  document.body.removeChild(span)
  return Math.ceil(width) // 存在宽度为小数的情况
}

使用教程

<BaseTable
  ref="refContentTable"
  v-loading="loading"
  :data="tableData"
  row-key="imei"
  style="margin-top: 10px"
>
  <TableColumn
    align="center"
    prop="imei"
    data-prop="imei"
    :label="$t('public.IMEI')"
    :column-width="columnWidthObj.imei"
  />
</BaseTable>

<script setup>
const loading = ref(false)
const refContentTable = ref(null)
const tableData = ref([])
const columnWidthObj = ref({})

const getDeviceList = () => {
  loading.value = true
  apiDeviceList({
    pageNum: pageNum.value,
    pageSize: pageSize.value,
    ...listParams.value
  })
    .then(({code, data}) => {
      if (code === '200' && data) {
        tableData.value = data.items
        useTableColumnWidth({
          refTable: refContentTable.value
        }).getTableColumnWidth(data => {
          columnWidthObj.value = data
        })
      }
    })
    .finally(() => {
      loading.value = false
    })
}

onMounted(() => {
  getDeviceList()
})
</script>

最终效果图

在这里插入图片描述


http://www.kler.cn/a/549263.html

相关文章:

  • Field ‘id‘ doesn‘t have a default value
  • Java 实现 Redis中的GEO数据结构
  • AtCoder Beginner Contest 393 —— E - GCD of Subset 补题 + 题解 python
  • Ubuntu添加桌面快捷方式
  • 深度学习在天文观测中的应用:解锁宇宙的奥秘
  • 虚拟环境测试部署应用
  • STM32的HAL库开发---内存保护(MPU)
  • python从入门到进去
  • 《探秘Windows 11驱动开发:从入门到实战》
  • 尚硅谷爬虫note007
  • leetcode:627. 变更性别(SQL解法)
  • 2025.2.13 Android Studio下载安装配置教程(详细版)
  • 1-10 github注册仓库
  • React VS Vue
  • 【Qt Qml】QML与C++交互
  • ubuntu20.04连接airpods pro2
  • 【Python】01-基础
  • SQL代码规范
  • 国内情智机器人:从“通情达理”到温暖陪伴的跨越
  • 基于51单片机的的鸡笼补光和恒温系统的设计与实现(源程序+Protues仿真+电路图+元件清单+器件手册)