使用popover实现:内容超出指定行打点...,且气泡框展示

在开发中遇到一个这种需求:内容超出一行打点...,且气泡框展示

虽然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>
     

这样,基本可以很好的实现这个效果了 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值