简单封装el-popover用于el-table-column里渲染

单行或多行文本溢出显示省略号,是很常见的需求。
然后今天遇到复杂点的需求,在el-table里有些单元格文本长,有些短,需要判断是否溢出,溢出时弹框显示所有文本。
判断文本是否溢出,参考此文 https://juejin.im/post/5d7798dc6fb9a06acc00af6c
但是,在el-table里,单元格是el-table-column渲染的,而el-popover好像没有提供相关处理逻辑,所以需要简单封装一下,以便在el-table-column 里渲染。

没有时间整理文字,暂记。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<template>
  <el-popover
    trigger="hover"
    placement="top"
    popper-class="popover-when-ellipsis"
    :title="title"
    :content="content"
    :disabled="disabled"
  >
    <div slot="reference" ref="reference" :class="ellipsisClass">
      {{ content }}
    </div>
  </el-popover>
</template>

<script>
export default {
  name: 'popover-when-ellipsis'
  /**
   * @props title: el-popover组件的标题  content: 要显示的内容
   *        multiline: 2行或3行,不传就默认是单行
   */
  props: {
    title: String,
    content: {
      type: String,
      required: true
    },
    multiline: {
      type: String,
      validator: (val) => ['2', '3'].indexOf(val) > -1
    }
  },

  data() {
    return {
      disabled: true,
      timer: null
    }
  },

  computed: {
    ellipsisClass() {
      return !this.multiline
        ? 'text-ellipsis'
        : 'text-ellipsis-' + this.multiline
    }
  },

  methods: {
    // 查看DOM可以发现Vue-popper里的tooltip元素是始终渲染的,disabled只是控制事件的绑定和解绑
    // 事件触发显示popper,是把tooltip元素appendChild移动到body下,动态定位并display: block显示
    // judge方法判断是否需要popper
    judge() {
      const el = this.$refs.reference
      if (!this.multiline) {
        this.disabled = !(el.clientWidth < el.scrollWidth) // disabled反逻辑
      } else {
        this.disabled = !(el.clientHeight < el.scrollHeight)
      }
    },

    // resize事件像scroll事件一样,也是会连续触发的
    throttle() {
      if (this.timer) {
        clearTimeout(this.timer)
      }
      this.timer = setTimeout(() => {
        this.judge()
      }, 500)
    }
  },

  mounted() {
    this.judge()
    window.addEventListener('resize', this.throttle)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.throttle)
  },
  // 表格数据翻页时,在el-table-column里渲染的只有数据内容改变,不会重新触发mounted,导致bug
  updated() {
    this.judge()
  }
}
</script>

全局样式里需要提供 .text-ellipsis .text-ellipsis-2 .text-ellipsis-3 以及 popover-when-ellipsis 四个类样式。

然后,就可以方便地进行循环渲染了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<el-table-column
    v-for="col in shownCols"
        :key="col.prop"
        :label="col.label"
        :width="col.width"
        :min-width="col.minWidth"
        :formatter="col.formatter"
    >
          <template slot-scope="scope">
            <popover-when-ellipsis
              v-if="colsNeedPopper.includes(col.prop)"
              :title="col.label"
              :content="scope.row[col.prop]"
              multiline="3"
            />
            <span v-else>{{ scope.row[col.prop] }}</span>
      </template>
 </el-table-column>

data 里可以集中管理数据,在 shownCols 数组里。