el-table
文件 element-ui/packages/table/src/table-body.js
截取部分代码
export default {
render(h) {
return (
<table>
<tbody>
{/* 表格内容 ... */}
{/* 一个表格 只渲染一个 tooltip */}
<el-tooltip effect={this.table.tooltipEffect} placement="top" ref="tooltip" content={this.tooltipContent}></el-tooltip>
</tbody>
</table>
);
},
created() {
this.activateTooltip = debounce(50, tooltip => tooltip.handleShowPopper());
},
methods: {
handleCellMouseEnter(event, row) { // 鼠标移入表格项 触发事件
const table = this.table;
const cell = getCell(event);
if (cell) {
const column = getColumnByCell(table, cell);
const hoverState = table.hoverState = { cell, column, row };
table.$emit('cell-mouse-enter', hoverState.row, hoverState.column, hoverState.cell, event);
}
// 判断是否text-overflow, 如果是就显示tooltip
const cellChild = event.target.querySelector('.cell');
if (!(hasClass(cellChild, 'el-tooltip') && cellChild.childNodes.length)) {
return;
}
// use range width instead of scrollWidth to determine whether the text is overflowing
// to address a potential FireFox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3
const range = document.createRange();
range.setStart(cellChild, 0);
range.setEnd(cellChild, cellChild.childNodes.length);
const rangeWidth = range.getBoundingClientRect().width;
const padding = (parseInt(getStyle(cellChild, 'paddingLeft'), 10) || 0) +
(parseInt(getStyle(cellChild, 'paddingRight'), 10) || 0);
if ((rangeWidth + padding > cellChild.offsetWidth || cellChild.scrollWidth > cellChild.offsetWidth) && this.$refs.tooltip) {
// 1. 判断: 如果宽度溢出
const tooltip = this.$refs.tooltip;
// TODO 会引起整个 Table 的重新渲染,需要优化
this.tooltipContent = cell.innerText || cell.textContent; // 2. 表格项内容 赋值给 tooltip显示
tooltip.referenceElm = cell; // 3. 替换referenceElm, tooltip通过Popper.js 计算显示的tooltip和referenceElm的相对位置
tooltip.$refs.popper && (tooltip.$refs.popper.style.display = 'none');
tooltip.doDestroy(); // 取消tooltip上一系列绑定事件
tooltip.setExpectedState(true);
this.activateTooltip(tooltip); // 4. 显示tooltip
}
},
handleCellMouseLeave(event) { // 鼠标溢出表格项 触发事件
const tooltip = this.$refs.tooltip;
if (tooltip) {
tooltip.setExpectedState(false);
tooltip.handleClosePopper(); // 隐藏tooltip
}
const cell = getCell(event);
if (!cell) return;
const oldHoverState = this.table.hoverState || {};
this.table.$emit('cell-mouse-leave', oldHoverState.row, oldHoverState.column, oldHoverState.cell, event);
},
}
}
记录点
- 鼠标事件
mouseenter
/mouseleave
(新),mouseover
/mouseout
(旧)
新的鼠标移入移出事件,去掉了冒泡和捕获的特性- mouseenter:鼠标第一次移动到元素区域时触发 (新)
- mouseleave:移出时触发(新)
- mousemove:在元素上移动时触发(一直触发)
- mouseover:鼠标移动到元素上时触发(旧)
- mouseout:从元素上移开时触发(旧)
- 步骤
-
el-tooltip
是tbody
的子节点,一个表格,只渲染一个el-tooltip
- 监听鼠标移入事件
mouseenter
,判断表格项内容是否溢出 - 如果溢出
- 表格项内容赋值给 tooltipContent 显示隐藏内容
- 替换
referenceElm
, tooltip通过Popper.js
计算显示的tooltip
和referenceElm
的相对位置 - 显示 tooltip
- 监听鼠标移开事件
mouseleave
,隐藏 tooltip
-
el-tooltip
文件 element-ui/packages/tooltip/src/main.js
截取部分代码文章来源:https://www.toymoban.com/news/detail-495133.html
const PopperJS = require('element-ui/src/utils/popper.js');
export default {
beforeCreate() {
this.popperVM = new Vue({
data: { node: '' },
render(h) {
return this.node;
}
}).$mount();
this.debounceClose = debounce(200, () => this.handleClosePopper());
},
render(h) {
if (this.popperVM) {
this.popperVM.node = (
<transition
name={ this.transition }
onAfterLeave={ this.doDestroy }>
<div
onMouseleave={ () => { this.setExpectedState(false); this.debounceClose(); } }
onMouseenter= { () => { this.setExpectedState(true); } }
ref="popper"
role="tooltip"
id={this.tooltipId}
aria-hidden={ (this.disabled || !this.showPopper) ? 'true' : 'false' }
v-show={!this.disabled && this.showPopper}
class={
['el-tooltip__popper', 'is-' + this.effect, this.popperClass]
}>
{/* 具名插槽 content 渲染在tooltip */}
{ this.$slots.content || this.content }
</div>
</transition>);
}
const firstElement = this.getFirstElement();
if (!firstElement) return null;
const data = firstElement.data = firstElement.data || {};
data.staticClass = this.addTooltipClass(data.staticClass);
return firstElement; // 找到默认插槽 default 显示在组件位置
},
mounted() {
this.referenceElm = this.$el;
// 给 referenceElm 绑定一系列事件, 包括: mouseenter mouseleave
// ...
if (this.value && this.popperVM) {
this.popperVM.$nextTick(() => {
if (this.value) {
this.updatePopper();
}
});
}
},
methods: {
updatePopper() {
const popperJS = this.popperJS;
if (popperJS) {
popperJS.update();
if (popperJS._popper) {
popperJS._popper.style.zIndex = PopupManager.nextZIndex();
}
} else {
this.createPopper();
}
},
createPopper() { // 省略...只剩下需要的逻辑
let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference;
const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper; // 提示信息ref 对应的DOM
const options = this.popperOptions;
if (!popper || !reference) return;
if (this.appendToBody) document.body.appendChild(this.popperElm); // 渲染在body节点下
/**
* reference: 默认插槽/鼠标移入移出显示tooltip相对的元素
* popper: 提示信息ref 对应的DOM (tooltip)
* option: 一些配置
*/
this.popperJS = new PopperJS(reference, popper, options);
// ...
}
}
}
记录点:文章来源地址https://www.toymoban.com/news/detail-495133.html
- render
- 找到默认插槽
default
显示在组件位置 - 提示信息:
transition
+ 具名插槽content
,鼠标移入referenceElm
,显示提示信息
- 找到默认插槽
- mounted:给 referenceElm 绑定一系列事件, 包括:
mouseenter
、mouseleave
,调用updatePopper
- 调用
createPopper
- 通过
Popper.js
计算显示的 提示信息 和 referenceElm 的相对位置 - 关键代码:
this.popperJS = new PopperJS(reference, popper, options);
- reference: 默认插槽/
referenceElm
,鼠标移入移出显示 提示信息 相对的元素 - popper: 提示信息ref 对应的DOM (tooltip)
- option: 一些配置
- reference: 默认插槽/
- 通过
到了这里,关于el-table溢出隐藏 鼠标移入显示tooltip逻辑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!