。
element-ui表单内tooltip可以让文字超出单元格时显示气泡,但是有一个限制,只能显示纯文本,无法控制tooptip内的样式,即使传入带标签的文本,也会把文本过滤出来,难以满足ui要求。
于是借用el-poper来实现,又有一个缺点,无论文字是否超出都会展示气泡,最后决定自己封装一个ellipsis组件,当元素内的文本超出元素展示省略号时,出现气泡。
思路:鼠标移入元素,比较元素的scrollHeight与clientHeight的大小,若滚动高度大于固定显示宽度,则文本是溢出状态。溢出状态时,创建气泡元素,计算好位置。
创建一个ellipsis组件:
<template> <div class="sllipsis-wraper" :style="{ '-webkit-line-clamp': lineClamp }" @mouseenter="mouseenter($event)" @mouseleave="mouseleave($event)" > <slot></slot> </div> </template> <script> export default { name: "ellipsis", props: { lineClamp: { //展示几行 type: Number, default: 1 }, tipText: { //提示值 type: Array | String, default: "" } }, computed: { bubbleId() { return `sllipsis-bubble-${this._uid}`; }, htmlStr() { if (Array.isArray(this.tipText)) { let str = ""; this.tipText.forEach(item => { str += `<span class="bublle-span">${item}</span>`; }); return str; } else { return this.tipText; } } }, data() { return {}; }, created() {}, methods: { mouseenter(e) { //鼠标移入 if (!this.tipText.length) return; var target = e.target, containerHeight = target.clientHeight, textHeight = target.scrollHeight, positionObj = target.getBoundingClientRect(), windowHeight = window.innerHeight, showLocation = windowHeight - positionObj.bottom < 50 ? "top" : "bottom"; if (textHeight > containerHeight) { //溢出 this.showBubble({ htmlStr: this.htmlStr, position: positionObj, showLocation: showLocation }); } else { //未溢出 this.hideBubble(); } }, mouseleave(e) { //鼠标移开 this.hideBubble(); }, createBubbleElement(data) { //创建提示框 let { htmlStr, position, showLocation } = data; if (!document.getElementById(this.bubbleId)) { let nodeEle = document.createElement("div"); nodeEle.id = this.bubbleId; this.setBubbleLocation(nodeEle,data); this.setBubbleContent(nodeEle,htmlStr); nodeEle.classList.add("is-block"); document.body.appendChild(nodeEle); } }, hideBubble() { // 隐藏提示框 let bubbleNode = this.getBubbleEle(); if (bubbleNode) { bubbleNode.classList.remove("is-block"); } }, showBubble(data) { // 展示提示框 let bubbleNode = this.getBubbleEle(); if (bubbleNode) { this.setBubbleLocation(bubbleNode,data); this.setBubbleContent(bubbleNode,data.htmlStr); bubbleNode.classList.add("is-block"); } else { //创建 this.createBubbleElement(data); } }, getBubbleEle() { //获取提示框元素 return document.getElementById(this.bubbleId); }, setBubbleLocation(DOM,data){ // 设置气泡位置 let { htmlStr, position, showLocation } = data; DOM.classList.add("is-block"); if (showLocation == "top") { DOM.style.top = ""; DOM.style.bottom = window.innerHeight - position.top + "px"; DOM.className = `sllipsis-bubble is-top`; DOM.style.setProperty('--bubble-allow-y', -12 + "px"); } else { DOM.style.bottom = ""; DOM.style.top = position.bottom + "px"; DOM.className = `sllipsis-bubble is-bottom`; DOM.style.setProperty('--bubble-allow-y', -12 + "px"); } DOM.style.left = position.left + "px"; DOM.style.setProperty('--bubble-allow-x', position.width/2 + "px"); }, setBubbleContent(DOM,content){ // 设置气泡内容 DOM.innerHTML = content; } } }; </script> <style lang="scss"> .sllipsis-wraper { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; } .sllipsis-bubble { position: fixed; max-width: 400px; background: #fff; border-radius: 4px; border: 1px solid #e4e6e9; padding: 6px; color: #333940; line-height: 1.4; font-size: 14px; box-shadow: 0 2px 4px 0 #e4e6e9; word-break: break-all; // z-index: 1; display: none; box-sizing: border-box; &::before { content: ""; position: absolute; width: 0; height: 0; border-width: 6px; border-style: solid; border-radius: 2px; z-index:2; left:var(--bubble-allow-x) } &.is-top::before{ bottom:var(--bubble-allow-y); border-color: #fff transparent transparent transparent; } &.is-bottom::before{ top:var(--bubble-allow-y); border-color: transparent transparent #fff transparent; } &.is-block { display: block; } &:hover { display: block; } .bublle-span { display: inline-block; border: 1px solid #e4e6e9; font-size: 12px; text-align: left; color: #333940; line-height: 18px; border-radius: 2px; margin-right: 4px; margin-top: 3px; margin-bottom: 3px; padding: 1px 2px; } } </style>
使用方法:
<ellipsis :lineClamp="1" tipText="xxx"> {{xxx}} </ellipsis>
超出一行隐藏时可省略lineClamp属性
效果:
。