el-table-column 二次封装支持根据内容自适应宽度

自定义组件源码

<template>
  <el-table-column
    v-if="$scopedSlots.default"
    v-bind="$attrs"
    :label="label"
    :prop="prop"
    :min-width="minWidth || calculWidth(listFieldName)"
    :formatter="formatter"
  >
    <template slot-scope="scope">
      <slot v-bind="scope" />
    </template>
  </el-table-column>
  <el-table-column
    v-else
    v-bind="$attrs"
    :label="label"
    :prop="prop"
    :min-width="minWidth || calculWidth(listFieldName)"
    :formatter="formatter"
  />
</template>

<script>
export default {
  name: "RyTableColumn",
  props: {
    label: {
      default: "",
      type: [String, Number],
    },
    prop: {
      default: "",
      type: String,
    },
    // 自定义最小宽度(可选)
    minWidth: {
      default: "",
      type: [String, Number],
    },
    // 自定义最大宽度(可选)
    maxWidth: {
      default: "",
      type: [String, Number],
    },
    // 自定义在数组列表中的字段名(可选)
    listFieldName: {
      default: "",
      type: String,
    },
    // 自定义需要计算宽度的字符串(可选)
    widthStr: {
      default: "",
      type: String,
    },
    // 自定义格式化方法(可选)
    formatter: {
      default: null,
      type: Function,
    },
    // 计算过滤器返回值的宽度(可选)
    widthFilter: {
      default: "",
      type: String,
    },
  },
  data() {
    return {};
  },
  created() {},
  methods: {
    calculWidth(listFieldName) {
      const { getStrWidth, maxWidth } = this;
      const labelStr = this.label + "WWW";
      // 获取源数据数组
      const listData = this.$parent.data ? this.$parent.data : [];
      // 设置宽度初始值
      let width = !this.widthStr ? getStrWidth(labelStr) : getStrWidth(this.widthStr);
      if (!this.widthStr && ((this.prop && !this.widthFilter) || this.formatter)) {
        const fieldName = listFieldName || this.prop;
        if (listData.length > 0) {
          // formatter方法
          const formatterFun = this.formatter;
          listData.forEach((item) => {
            // 计算每行宽度
            const itemWidth = formatterFun ? getStrWidth(formatterFun(item)) : getStrWidth(item[fieldName]);
            width = Math.max(itemWidth, width);
          });
        }
      } else if (this.widthStr) {
        // 包含花括号
        const reBracketContentIn = /\{(.+?)\}/g;
        // 不包含花括号
        const reBracketContentEx = /(?<=\{)(.+?)(?=\})/g;
        const bracketContentArr = this.widthStr.match(reBracketContentEx);
        if (bracketContentArr) {
          width = getStrWidth(labelStr);
          listData.forEach((listItem) => {
            let arrIndex = 0;
            let repContentArr = [];
            // 获取需要赋值的数组
            bracketContentArr.forEach((bItem, bIndex) => {
              for (const field in listItem) {
                if (bItem == field) {
                  repContentArr[bIndex] = listItem[field];
                }
              }
            })
            // 字符串相应位置替换为数组中对应的值
            const repWidthStr = this.widthStr.replace(reBracketContentIn, () => {
              const resStr = repContentArr[arrIndex]
              arrIndex++;
              return resStr;
            })
            width = Math.max(getStrWidth(repWidthStr), width);
          });
        }
      } else if (this.widthFilter) {
        // 包含中括号
        const reBracketContentIn = /\[(.+?)\]/g;
        // 不包含中括号
        const reBracketContentEx = /(?<=\[)(.+?)(?=\])/g;
        const bracketContentArr = this.widthFilter.match(reBracketContentEx);
        if (bracketContentArr) {
          listData.forEach((row) => {
            let arrIndex = 0;
            let repContentArr = [];
            bracketContentArr.forEach((item) => {
              const filterFun = this.$options.filters[item.split("|")[1].trim()];
              const paramName = item.split("|")[0].trim();
              const resField = filterFun(row[paramName])
              repContentArr.push(resField);
            })
            const repWidthFilterStr = this.widthFilter.replace(reBracketContentIn, () => {
              const resStr = repContentArr[arrIndex]
              arrIndex++;
              return resStr;
            })
            width = Math.max(getStrWidth(repWidthFilterStr), width);
          })
        } else {
          const filterFun = this.$options.filters[this.widthFilter.split("|")[1].trim()];
          const paramName = this.widthFilter.split("|")[0].trim();
          listData.forEach((row) => {
            const resField = filterFun(row[paramName])
            width = Math.max(getStrWidth(resField), width);
          })
        }
      }
      return maxWidth && (width > maxWidth) ? maxWidth : Math.max(100, width);
    },
    // 获取字符串中的字符数量
    getCharNumber(charType, str) {
      if (!charType || !str) {
        return 0;
      }
      str = str.toString();
      let resNum = 0;
      let inArr;
      switch (charType) {
        // 中文字符
        case "zh":
          resNum = str.match(/[\u4E00-\u9FA5]/g) ? str.match(/[\u4E00-\u9FA5]/g).length : 0;
          break;
        // 英文大写字符
        case "enUp":
          resNum = str.match(/[\A-Z]/g) ? str.match(/[\A-Z]/g).length : 0;
          break;
        // 英文小写字符
        case "enLow":
          resNum = str.match(/[\a-z]/g) ? str.match(/[\a-z]/g).length : 0;
          break;
        // 数字字符
        case "num":
          resNum = str.match(/[0-9]/g) ? str.match(/[0-9]/g).length : 0;
          break;
        // 短字符
        case "short":
          resNum = str.match(/[:;'.,!*|]/g) ? str.match(/[:;'.,!*|]/g).length : 0;
          break;
        // 其他字符
        case "other":
          inArr = str.match(/[\u4E00-\u9FA5\A-Z\a-z0-9:;'.,!*|]/g);
          resNum = str.length - (inArr ? inArr.length : 0);
          break;
        default:
          resNum = 0;
      }
      return resNum;
    },
    // 计算字符串长度
    getStrWidth(str) {
      if (!str) {
        return 0;
      }
      str = str.toString();
      // 每个中文字符占用宽度
      const zhPerWidth = 18.8;
      // 每个英文大写字符占用宽度
      const enUpPerWidth = 11;
      // 每个英文小写字符占用宽度
      const enLowPerWidth = 8.5;
      // 每个数字字符占用宽度
      const numPerWidth = 11;
      // 每个短字符占用宽度
      const shortPerWidth = 6;
      // 每个其他字符占用宽度
      const otherPerWidth = 12;
      const colZhLenWidth = this.getCharNumber("zh", str) * zhPerWidth;
      const colEnUpLenWidth = this.getCharNumber("enUp", str) * enUpPerWidth;
      const colEnLowLenWidth = this.getCharNumber("enLow", str) * enLowPerWidth;
      const colNumLenWidth = this.getCharNumber("num", str) * numPerWidth;
      const colShortLenWidth = this.getCharNumber("short", str) * shortPerWidth;
      const colOtherLenWidth = this.getCharNumber("other", str) * otherPerWidth;
      return colZhLenWidth + colEnUpLenWidth + colEnLowLenWidth + colNumLenWidth + colShortLenWidth + colOtherLenWidth;
    },
  },
};
</script>

<style lang="scss" scoped>
</style>

简单说明

基本原理为根据内容中中文字符和其他字符的长度计算需要占用的宽度

标签内可用属性

1、格式化(自动计算格式化后的字符串长度):
:formatter="(row)=>{return row.cardId + 'WWwww'}"

2、过滤器(自动计算过滤器结果字符串的长度,只支持全局过滤器):
width-filter="createDate | getDateTimeFn1"
可支持多个过滤器:
width-filter="[createDate | getDateTimeFn1]   [createDate | getDateTimeFn1]"

3、自定义用来计算宽度的字符串,按照配置的内容计算宽度:
:width-str="'    '+$t('preDepositAcct.list.modify')+$t('cardManagement.delete')"

4、增加原组件不支持的最大宽度的配置:
max-width="200"

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值