文本溢出才显示el-tooltip,并且只生成一个dom插入到文档中

1 篇文章 0 订阅
1 篇文章 0 订阅

基于el-tooltip二次封装的tool-tip-ellipsis全局气泡提示


输出背景

el-select下拉组件中的el-option,通常有多个,需要遍历出来,也有做成滚动加载更多el-option的。这些el-option显示的内容可能会很长,如果不作处理,下拉框会拉的很长,这时候就可能需要实现缺省显示(超出长度的显示…),当鼠标移上去的时候就显示完整的内容。

一般的做法是el-option中先用css实现缺省显示,然后再给遍历出来的每一个el-option都加一个el-tooltip。这样的优点是快,且简单,缺点是每一个el-option,都会生成一个对应的el-tooltip,相当于一对一的关系。也就是说,如果你遍历了100个el-option,然后你又都用鼠标hover了一遍,那就会生成100个el-tooltip插入到文档中,看下图。
在这里插入图片描述
上图有6个元素加了el-tooltip,全都hover了一遍,控制台可以看到生成了6个div

优化方案

1、全局(vuex)共用一个el-tooltip实例globalTemplateToolTip,这是个容器。
2、再写一个触发globalTemplateToolTip显示的组件tool-tip-ellipsis,调用这个组件是,会把你想要显示的内容放到globalTemplateToolTip。用这个组件代替平时写的el-tooltip,而这个组件的工作就是在内部改变el-tooltip的触发方式,使其hover时不再额外生成新的dom。
3、只有文本溢出时才显示el-tooltip的hover内容。利用css样式并结合js来判断文本是否溢出。

话不多说,开始

1、el-tooltip容器

先全局挂在,比如放到APP.vue里,根据自己的项目结构做调整

APP.vue

<router-view v-if="isRouterAlive" />
<global-template-tool-tip></global-template-tool-tip>

import globalTemplateToolTip from '@/components/tool-tip'

Tool-tip.vue

<template>
    <el-tooltip ref="globalTemplateTip" :content="toolTipContent" :placement="toolTipPlacement"></el-tooltip>
</template>

mounted() {
	this.$store.commit(‘MOUNT_TOOL_TIP', this.$refs.globalTemplateTip)
}

MOUNT_TOOL_TIP(state, node) {
	state.toolTip = node
},
2、封装el-tooltip组件(这个是直接在组件中使用的,上面的是容器,用来存放hover出来的气泡提示的)

tool-tip-ellipsis.vue

<template>
    <div @mouseenter="tipBoxEnter($event)" @mouseleave="tipBoxLeave($event)">
        <p :class="['too-tip-content-p', optionMaxWidth ? 'max-width-' + optionMaxWidth : '']">
            <slot></slot>
        </p>
    </div>
</template>
<script>
export default {
    props: {
	  // 最大宽度,可忽略
        optionMaxWidth: {
            type: Number
        },
	  // 内容
        toolTipContent: {
            type: String,
            default: ''
        },
	  // 位置
        placement: {
            type: String,
            default: 'bottom'
        }
    },
    methods: {
        tipBoxEnter(e) {
            // 获取挂载的p标签
            let p_Node = e.target.querySelector('.too-tip-content-p')
            // 如果文本溢出
            if (p_Node.scrollWidth > p_Node.offsetWidth) {
                // 初始化全局toolTip
                this.$store.commit('INIT_TOOL_TIP', {
                    node: p_Node,
                    content: this.toolTipContent,
                    placement: this.placement
                })
            }
        },
        tipBoxLeave(e) {
            // 销毁toolTip
            this.$store.commit('CLOSE_TOOL_TIP')
        }
    }
}
</script>
<style lang="scss" scoped>
.too-tip-content-p {
    padding: 0;
    margin: 0;
    text-overflow: ellipsis;
    overflow: hidden;
}
</style>

上面的max-width-xxx的类名是使用scss的循环、占位符等实现的。
请注意,这样写会生成大量的类名,打包出的css文件会变大,慎用。

// 最大宽度
$max_width_i: 1000;
$maxWidthList: ();

@while $max_width_i>0 {
    $maxWidthList: append($maxWidthList, $max_width_i, comma);
    $max_width_i: $max_width_i - 1;
}

@each $len in $maxWidthList {
    %max-width-#{$len} {
        max-width: #{$len}px;
    }

    .max-width-#{$len} {
        @extend %max-width-#{$len};
    }
}

vuex

// 初始化
INIT_TOOL_TIP(state, obj) {
	state.toolTip.referenceElm = obj.node
	// 先消掉之前的
	state.toolTip.$refs.popper &amp;&amp; (state.toolTip.$refs.popper.style.display = 'none')
	state.toolTip.doDestroy()
	// 设置组件内的条件变量为true,否则无法调用handleClosePopper
	state.toolTip.setExpectedState(true)
	// 展示新的tool-tip
	activateTooltip(state.toolTip)
	// 填入内容
	state.toolTipContent = content
	// 设置位置
	state.toolTipPlacement = placement
},

// 关闭
CLOSE_TOOL_TIP(state) {
	state.toolTip.setExpectedState(false)
	state.toolTip.handleClosePopper()
}
toolTip源码

在这里插入图片描述

在这里插入图片描述

使用

<el-option
	v-for="(option, optIndex) in self_list"
	:key="optIndex + '-' + option.id"
	:label="option[dictLabel] || '—'"
	:value="option"
>
	<toolTipEllipsis
		:optionMaxWidth="200"
		:toolTipContent="option.content
		:placement="'top-start'"
	>
		{{ option.content }}
	</toolTipEllipsis>
</el-option>


import toolTipEllipsis from '@/components/tool-tip-ellipsis/index’

效果

在这里插入图片描述

总结

挺有意思的一次尝试,希望能帮到有需要的人。为了不显得冗长,节省了很多代码,有不当之处,欢迎指出!

参考链接:
https://blog.csdn.net/sgabon/article/details/106426738

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值