在开发中遇到一个这种需求:内容超出一行打点...,且气泡框展示
虽然elementui 里 el-table 有一个属性可以很好的实现:给el-table-column 加 show-overflow-tooltip 属性,可以使列表里的内容超出隐藏并展示气泡框;但是这只适合限制整个el-table-column里的内容,做不到对其中一个内容实现这样的效果,所以还要另寻他法。
其中,有两种比较简便的方法大概实现需求
1、直接使用tooltip:但这样就会出现,无论一行能不能展示全,都会出现气泡框,显然不符合需求。
2、判断字符长度:如果内容的长度大于设置的长度就气泡框展示,但这样会因英文或特殊符号与中文的宽度不等,导致判断不精准,出现不打点也会出现气泡框。
所以最好的方法就是计算容器的宽度,使内容超出此宽度就会出现气泡框,加入行数就是:容器宽度 * 行数 < 内容宽度 时展示气泡框
封装成组件的代码:
<template>
<div class="auto-popover">
<el-popover
:title="title"
:width="width"
:offset="offset"
:transition="transition"
:popper-options="popperOptions"
:open-delay="openDelay"
:placement="placement"
:trigger="trigger"
:disabled="!showBubble"
>
<!-- 不启用插槽,则气泡内容默认和content一直,为传入popoverValue -->
<template v-if="useSlot">
<!-- 启用插槽,如果只启用content,则气泡内容和content一致 -->
<slot v-if="useSlotBubble" name="bubble" />
<p v-else class="my-popover">
<slot name="content" />
</p>
</template>
<p v-else class="my-popover">{{ popoverValue }}</p>
<div slot="reference">
<div
ref="container"
:class="{
'plain-ellipsis': rows == 1,
'auto-popover-ellipsis': rows != 1,
'auto-popover_row-2': rows == 2,
'auto-popover_row-3': rows == 3,
'auto-popover_row-4': rows == 4,
'auto-popover_row-5': rows == 5,
'auto-popover_row-6': rows == 6,
'auto-popover_row-7': rows == 7,
'auto-popover_row-8': rows == 8,
'auto-popover_aligin-left': aligin==='left',
}"
>
<slot v-if="useSlotContent" name="content" />
<span v-else>{{ popoverValue }}</span>
</div>
<!-- 计算宽度 -->
<div v-if="useSlot" ref="content" class="cal-content">
<slot name="content" />
</div>
<div v-else ref="content" class="cal-content">
<span>{{ popoverValue }}</span>
</div>
</div>
</el-popover>
</div>
</template>
<script>
export default {
name: 'AutoPopover',
components: {},
props: {
popoverValue: {
type: String,
default: ''
},
// 行数
rows: {
type: [Number, String],
default: 1
},
// 强制展示bubble,不用计算
forceShowBubble: {
type: Boolean,
default: false
},
// 文字对齐方式
aligin: String,
trigger: { type: String, default: 'hover' },
title: String,
width: {
type: String,
default: '150px'
},
offset: {
type: Number,
default: 0
},
transition: String,
popperOptions: Object,
popperClass: String,
openDelay: Number,
placement: String
},
data() {
return {
showBubble: false
}
},
computed: {
// 是否采用slot方式
useSlot() {
return Object.keys(this.$slots).length
},
useSlotContent() {
return Object.keys(this.$slots).indexOf('content') > -1
},
useSlotBubble() {
return Object.keys(this.$slots).indexOf('bubble') > -1
}
},
watch: {
popoverValue: {
handler(val) {
this.$nextTick(() => {
this.calculateWidth()
})
},
immediate: true
}
},
mounted() {},
methods: {
// 计算实际内容和容器之间的宽度关系
calculateWidth() {
const container = this.$refs.container
const content = this.$refs.content
const rows = +this.rows
const containerW = container.offsetWidth
const contentW = content.offsetWidth
// console.log(containerW - 8);
this.showBubble = this.forceShowBubble || (containerW - 8) * rows < contentW
// console.log(this.showBubble)
}
}
}
</script>
<style lang='scss' scoped>
.auto-popover {
.cal-content {
white-space: nowrap;
display: inline-block;
position: absolute;
left: -100000px; // fix:防止影子dom在容器中撑开容器,影响实际宽度,比如table里
visibility: hidden;
}
.auto-popover-ellipsis {
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
}
.auto-popover_row-2 {
-webkit-line-clamp: 2;
}
.auto-popover_row-3 {
-webkit-line-clamp: 3;
}
.auto-popover_row-4 {
-webkit-line-clamp: 4;
}
.auto-popover_row-5 {
-webkit-line-clamp: 5;
}
.auto-popover_row-6 {
-webkit-line-clamp: 6;
}
.auto-popover_row-7 {
-webkit-line-clamp: 7;
}
.auto-popover_row-8 {
-webkit-line-clamp: 8;
}
.auto-popover_aligin-left {
text-align: left;
}
}
</style>
<style lang="scss">
.my-popover {
max-width: 300px;
word-wrap: break-word;
word-break: keep-all;
}
.plain-ellipsis {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
</style>
使用组件时:import AutoPopover from '@/components/AutoPopover'
<!-- 审核状态 -->
<el-table-column prop="checkStatus" v-bind="tableColumnAttributes" label="审核状态" min-width="150">
<template v-slot="scope">
<!-- 审核驳回时展示原因,一行打点,气泡框展示 -->
<AutoPopover
v-show="scope.row.checkStatus === 2"
:popover-value="'原因:' + scope.row.checkReason"
placement="top" />
</template>
</el-table-column>
组件默认是展示一行
显示结果:
如果content内容和bubble内容不同,则content通过popoverValue传递,bubble通过插槽自定义,并设置forceShowBubble属性为true:
<el-table-column prop="checkStatus" v-bind="tableColumnAttributes" label="通过插槽自定义" min-width="150">
<template slot-scope="scope">
<AutoPopover forceShowBubble :popoverValue="row.date">
<p style="width: 300px;word-break:break-all" slot='bubble'>
{{ scope.row.checkReason }}
</p>
</AutoPopover>
</template>
</el-table-column>
<!-- 设置行数 -->
<el-table-column prop="checkStatus" v-bind="tableColumnAttributes" label="设置二行" min-width="150">
<template slot-scope="scope">
<AutoPopover :rows="2" :popoverValue="scope.row.checkReason"></AutoPopover>
</template>
</el-table-column>
这样,基本可以很好的实现这个效果了