单行或多行文本溢出显示省略号,是很常见的需求。
然后今天遇到复杂点的需求,在el-table里有些单元格文本长,有些短,需要判断是否溢出,溢出时弹框显示所有文本。
判断文本是否溢出,参考此文 https://juejin.im/post/5d7798dc6fb9a06acc00af6c
但是,在el-table里,单元格是el-table-column渲染的,show-overflow-tooltip只支持单行,而el-popover好像没有提供相关处理逻辑,所以需要简单封装一下,以便在el-table-column 里渲染。
没有时间整理文字,暂记。
<template>
<el-popover
trigger="hover"
placement="top"
popper-class="popover-when-ellipsis"
:title="title"
:content="popperContent"
:disabled="disabled"
v-bind="$attrs"
>
<slot name="content"></slot>
<div slot="reference" ref="reference" :class="ellipsisClass">
{{ content }}
</div>
</el-popover>
</template>
<script>
export default {
name: 'popover-when-ellipsis'
/**
* @props title: el-popover组件的标题 content: 要显示的内容 slot传入的DOM优先,覆盖掉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
},
popperContent() {
// 看el-popover源码,传不传content这个prop主要是影响样式,传了会多一个el-popover--plain类名,padding更大
if (!this.$slots.content) return this.content
return undefined
}
},
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
四个类样式。
然后,就可以方便地进行循环渲染了。
<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
数组里。