useTextEllipsis
该 hook 用于获取设置了单行文本超出显示省略号样式的元素的状态(是否显示了省略号)。
实现源码
ts
import { ref, onMounted, onScopeDispose } from 'vue';
const getPadding = (el: HTMLElement) => {
const style = window.getComputedStyle(el, null);
const paddingLeft = Number.parseInt(style.paddingLeft, 10) || 0;
const paddingRight = Number.parseInt(style.paddingRight, 10) || 0;
const paddingTop = Number.parseInt(style.paddingTop, 10) || 0;
const paddingBottom = Number.parseInt(style.paddingBottom, 10) || 0;
return {
left: paddingLeft,
right: paddingRight,
top: paddingTop,
bottom: paddingBottom
};
};
const checkEllipsis = (el: HTMLElement) => {
const { left, right } = getPadding(el);
const childElement = el.children[0] as HTMLElement;
if (!childElement) {
return false;
}
const childElementWidth = left + right + childElement.offsetWidth;
return el.clientWidth <= childElementWidth;
};
/**
* 文本是否溢出(创建block元素来包裹inline元素)
* @param isAutoUpdate dom变化后是否自动更新状态(MutationObserver),默认为true
* @returns
*/
export const useTextEllipsis = (isAutoUpdate = true) => {
const blockRef = ref<HTMLElement | null>(null);
const isEllipsis = ref(false);
const updateStatus = () => {
if (!blockRef.value) {
return;
}
const element = blockRef.value;
isEllipsis.value = checkEllipsis(element);
};
let observer: MutationObserver | null = null;
onMounted(() => {
if (isAutoUpdate) {
observer = new MutationObserver(updateStatus);
observer.observe(blockRef.value!, {
childList: true,
subtree: true,
characterData: true
});
}
updateStatus();
});
onScopeDispose(() => {
if (observer) {
observer.disconnect();
observer = null;
}
});
return {
blockRef,
isEllipsis,
updateStatus
};
};介绍
该 hook 接收一个布尔值参数,用来设置是否自动监听dom元素的变化并变更状态。
返回值为一个对象,包含以下属性:
isEllipsis是否显示了省略号;updateStatus更新状态函数;blockRef用于绑定到需要监听的dom元素。
使用
配合ant-design-vue的tooltip组件,可以实现文本超出了,才显示完整文字气泡提示的效果。
点我改变文本内容
千山鸟飞绝,万径人踪灭。孤舟蓑笠翁,独钓寒江雪。
示例代码
vue
<script lang="ts" setup>
import { Tooltip } from 'ant-design-vue';
import { ref } from 'vue';
import { useTextEllipsis } from '@utils/hooks/useTextEllipsis';
const { blockRef, isEllipsis } = useTextEllipsis();
const text = ref('千山鸟飞绝,万径人踪灭。孤舟蓑笠翁,独钓寒江雪。');
const onChangeText = () => {
if (text.value.length > 20) {
text.value = '大梦一场三百年,人生几度梦中看。';
} else {
text.value = '千山鸟飞绝,万径人踪灭。孤舟蓑笠翁,独钓寒江雪。';
}
};
</script>
<template>
<div class="text" @click="onChangeText">点我改变文本内容</div>
<div class="container">
<tooltip>
<template v-if="isEllipsis" #title>{{ text }}</template>
<div ref="blockRef" class="ellipsis">
<span>{{ text }}</span>
</div>
</tooltip>
</div>
</template>
<style lang="scss" scoped>
.text {
margin-bottom: 10px;
cursor: pointer;
color: #1890ff;
}
.container {
width: 300px;
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
}
</style>