Ellipsis 文本溢出组件封装

31 阅读1分钟

文本溢出组件封装

文本溢出检测与提示: 当文本内容超出容器宽度时自动显示省略号,并在hover时显示完整内容的Tooltip。类似 el-tableshow-overflow-tooltip 效果

1. 涉及知识点

  1. lodash的 throttle 方法
  2. 浏览器内置API ResizeObserver
  3. JSX语法

2. 原理

使用ResizeObserver监听指定元素的宽度,对比元素实际内容宽度与元素可视区域宽度,控制悬浮是否展示,结合样式实现文本溢出...展示

3. 代码实现

  1. index.js
import { throttle } from 'lodash';
import './index.less';

export default {
    name: 'qEllipsis',
    // 关闭属性继承, 防止父组件的属性传递到子组件
    inheritAttrs: false,
    props: {
        // 文本内容
        content: {
            type: [String, Number],
            default: null
        }
    },
    data() {
        return {
            disabled: false,
            resizeObserverInstance: null
        };
    },
    mounted() {
        this.init();
    },
    beforeDestroy() {
        if (this.resizeObserverInstance) {
            // disconnect(): 停止观察所有已注册的目标元素, 一次性清空所有观察目标
            // unobserve(): 停止对指定单个目标的观察,选择性移除
            this.resizeObserverInstance.disconnect?.();
            this.resizeObserverInstance = null;
        }
    },
    methods: {
        init() {
            const { contentRef } = this.$refs;
            if (!contentRef) {
                return;
            }
            // ResizeObserver: 浏览器内置API, 是用于监听元素尺寸变化的API
            const resizeObserverInstance = new ResizeObserver(
                throttle(entries => {
                    entries.forEach(item => {
                        if (item.target !== contentRef) {
                            return;
                        }
                        const { scrollWidth, clientWidth } = contentRef;

                        // 判断内容是否溢出,溢出则显示 tooltip
                        this.disabled = clientWidth >= scrollWidth;
                    });
                }, 1e2)
            );
            // 监听目标元素尺寸变化
            resizeObserverInstance.observe(contentRef);
            this.resizeObserverInstance = resizeObserverInstance;
        }
    },
    // 渲染函数
    render() {
        const { content, disabled, $listeners, $attrs, $slots } = this;
        const tooltipAttrs = {
            placement: 'top',
            ...$attrs,
            disabled
        };

        return (
            // $slots.content: 具名插槽 content(<template #content>)
            // content: content 属性
            // $slots.default: 默认插槽内容
            <el-tooltip {...{ attrs: tooltipAttrs }}>
                <template slot="content">{$slots.content || content || $slots.default}</template>
                <div ref="contentRef" class="q-ellipsis" {...{ on: $listeners }}>
                    {$slots.content || content || $slots.default}
                </div>
            </el-tooltip>
        );
    }
};

  1. index.less
.q-ellipsis {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
}

4. 使用示例

<!-- 三种使用方式 -->
<Ellipsis content="简短文本" effect="light" />

<Ellipsis effect="light">
    <template #content>长文本内容...</template>
</Ellipsis>

<Ellipsis effect="light">
    默认插槽内容...
</Ellipsis>