likes
comments
collection
share

React组件封装实践:构建一个正确处理ellipsis和tooltip的便利贴组件

作者站长头像
站长
· 阅读数 2

Web开发中,组件化的设计模式已经成为提高开发效率和界面一致性的重要手段。特别是在处理文本显示时,如何有效地展示内容,并在内容过长时提供用户友好的交互方式,成为了设计中的一大挑战。本文将介绍如何从零开始,使用React框架构建一个具备文本溢出处理功能的“便利贴”组件。

需求分析

首先,明确组件需要满足的基本功能需求:

  1. 自定义字体大小和宽度:允许通过属性定制组件的显示样式。
  2. 限定最大显示行数:超过指定行数的文本内容需要被隐藏,并以省略号表示。
  3. 鼠标悬浮显示完整内容:当文本被截断时,鼠标悬浮应显示一个tooltip以查看全部内容。

初步设计

基于上述需求,设计了StickyNote组件,它不仅提供了基本的文本展示功能,还通过CSS样式控制文本的溢出显示,并使用了React的状态管理和事件处理机制来实现鼠标悬浮时的tooltip交互。

组件实现

import { isDarkTheme } from '@src/lib/common';
import React, { useState, useEffect, useRef } from 'react';

/**
 * 文本组件,可根据内容自动展示工具提示。
 *
 * @component
 * @param {Object} props 组件的props
 * @param {string} props.text 要展示的文本内容
 * @param {number} [props.marginLeft=0] 文本的左外边距
 * @param {number} [props.fontSize=16] 字体大小
 * @param {number|string} [props.width=200] 组件宽度,可以是数字或字符串,例如'200px'
 * @param {number} [props.maxLine=3] 最大显示行数,超出部分将被隐藏并显示省略号
 * @param {boolean} [props.tooltip=true] 是否在文本溢出时显示工具提示
 * @param {string} [props.lineHeight='130%'] 行高,可以是数字或百分比
 * @param {string} [props.fontWeight=`var(--hc-font-bold)`] 字体粗细
 * @param {string} [props.darkColor] 暗色主题下的文本颜色
 * @param {string} props.color 文本颜色,当没有指定暗色主题颜色时,在暗色主题下使用
 */
const MyText = ({ 
  text, 
  marginLeft = 0,
  fontSize = 16, 
  width = 200, 
  maxLine = 3,
  tooltip = true, 
  lineHeight = '130%',
  fontWeight = `var(--hc-font-bold)`,
  darkColor,
  color,
}) => {
  const [isOverflow, setIsOverflow] = useState(false); // 状态:是否文本溢出
  const [showTooltip, setShowTooltip] = useState(false); // 状态:是否显示工具提示
  const textRef = useRef(null); // 引用:文本容器

  // 检查文本是否溢出
  useEffect(() => {
    const checkOverflow = () => {
      const element = textRef.current;
      setIsOverflow(element.scrollHeight > element.clientHeight); // 判断内容高度是否大于容器高度
    };
    checkOverflow();
  }, [text]); // 依赖变量:text

  // 鼠标进入时的处理函数
  const handleMouseEnter = () => isOverflow && setShowTooltip(true);
  // 鼠标离开时的处理函数
  const handleMouseLeave = () => setShowTooltip(false);

  return (
    <div
      style={{ 
        position: 'relative', 
        marginLeft,
        width, 
        fontSize, 
        flex: `0 0 ${width}px`,
        lineHeight,
        fontWeight,
        color: isDarkTheme() ? darkColor ?? color : color, // 根据主题选择颜色
      }}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    >
      <div
        ref={textRef}
        style={{
          overflow: 'hidden',
          textOverflow: 'ellipsis',
          display: '-webkit-box',
          WebkitLineClamp: maxLine,
          WebkitBoxOrient: 'vertical',
        }}
      >
        {text}
      </div>
      {showTooltip && tooltip && (
        <div
          style={{
            position: 'absolute',
            bottom: '100%',
            left: '0',
            backgroundColor: 'black',
            color: 'white',
            padding: '5px',
            borderRadius: '5px',
            fontSize: '14px',
            whiteSpace: 'nowrap',
            transform: 'translateY(-5px)',
            zIndex: 1000,
          }}
        >
          {text}
        </div>
      )}
    </div>
  );
};

export default MyText;

详细说明

  1. 样式自定义:组件接收fontSizewidth属性,允许调用者根据需要设置组件的字体大小和宽度,以适应不同的布局需求。
  2. 最大显示行数与文本溢出处理:通过CSS的-webkit-box布局和WebkitLineClamp属性,实现了文本的最大行数限制和溢出内容的隐藏,显示为省略号。这种方式简洁高效,能够满足大多数浏览器的兼容性要求。
  3. 动态Tooltip展示:组件利用React的useStateuseEffect钩子,在组件挂载后判断文本是否溢出。若溢出,则设置isOverflow状态为true,并通过鼠标的悬浮事件动态显示和隐藏Tooltip,showTooltip状态控制Tooltip的显示。
  4. Tooltip定位:Tooltip通过绝对定位相对于文本容器定位,使用bottom: '100%'transform: 'translateY(-5px)'确保Tooltip位于文本容器正上方并略有偏移,避免直接覆盖在文本上,影响阅读。

总结

通过以上步骤,我们成功构建了一个功能完备的“便利贴”组件,它不仅支持自定义样式,还能智能处理文本溢出,并在必要时通过Tooltip提供完整内容的预览。这一过程展示了如何结合React的强大功能和CSS的灵活样式处理,来解决实际开发中的常见问题,同时也体现了组件化开发模式在提高开发效率和保证界面一致性方面的重要作用。

在构建类似组件时,重要的是不仅要关注功能的实现,还要考虑用户的实际需求和使用体验。通过不断地迭代和优化,可以使组件更加健壮和易用,从而为最终用户提供更加优质的界面和交互体验。