React 仅针对具有省略号的文本显示 Material-UI 工具提示

IT技术 reactjs react-redux tooltip material-ui ellipsis
2021-04-27 09:39:21

寻找一种方法,使 material-ui 的工具提示在文本被省略号(溢出)截断时才展开表格单元格中的文本。

目前在我的表中,我有一个这样的单元格:

<TableCell className={classes.descriptionCell}>{row.description}</TableCell>

我的 descriptionCell 样式是这样的:

    descriptionCell: {
        whiteSpace: 'nowrap',
        maxWidth: '200px',
        overflow: 'hidden',
        textOverflow: 'ellipsis'
    }

这使得文本在此表格中表现得如我所愿,但我希望能够悬停并在工具提示中查看其余部分,最好是 Material-UI 的内置工具提示组件。

我知道这里有一个包https://www.npmjs.com/package/react-ellipsis-with-tooltip应该这样做,但它使用引导工具提示,而不是材料 UI。

4个回答

离开@benjamin.keen 的回答。这是一个独立的功能组件,它只是他使用钩子执行比较功能的答案的扩展。

import React, { useRef, useEffect, useState } from 'react';
import Tooltip from '@material-ui/core/Tooltip';
const OverflowTip = props => {
  // Create Ref
  const textElementRef = useRef();

  const compareSize = () => {
    const compare =
      textElementRef.current.scrollWidth > textElementRef.current.clientWidth;
    console.log('compare: ', compare);
    setHover(compare);
  };

  // compare once and add resize listener on "componentDidMount"
  useEffect(() => {
    compareSize();
    window.addEventListener('resize', compareSize);
  }, []);

  // remove resize listener again on "componentWillUnmount"
  useEffect(() => () => {
    window.removeEventListener('resize', compareSize);
  }, []);

  // Define state and function to update the value
  const [hoverStatus, setHover] = useState(false);

  return (
    <Tooltip
      title={props.value}
      interactive
      disableHoverListener={!hoverStatus}
      style={{fontSize: '2em'}}
    >
      <div
        ref={textElementRef}
        style={{
          whiteSpace: 'nowrap',
          overflow: 'hidden',
          textOverflow: 'ellipsis'
        }}
      >
        {props.someLongText}
      </div>
    </Tooltip>
  );
};

export default OverflowTip;

基于 benjamin.keen 的回答,这是他的代码的功能版本:

import React, { useRef, useState, useEffect } from 'react';
import Tooltip from '@material-ui/core/Tooltip';

const OverflowTip = ({ children }) => {
  const [isOverflowed, setIsOverflow] = useState(false);
  const textElementRef = useRef();
  useEffect(() => {
    setIsOverflow(textElementRef.current.scrollWidth > textElementRef.current.clientWidth);
  }, []);
  return (
    <Tooltip title={children} disableHoverListener={!isOverflowed}>
      <div
        ref={textElementRef}
        style={{
          whiteSpace: 'nowrap',
          overflow: 'hidden',
          textOverflow: 'ellipsis',
        }}
      >
        {children}
      </div>
    </Tooltip>
  );
};

请在下面找到代码和框 - https://codesandbox.io/s/material-demo-p2omr

我在这里使用 ref 来获取 TableCell DOM 节点,然后比较 scrollWidth 和 clientWidth 以确定是否必须显示 Tooltip。(这是基于这里的答案

我已将“rowref”(具有 ref 的属性)和“open”(禁用/启用工具提示)添加为行的新属性。我不知道您的数据来自哪里,但我假设您可以将这些属性添加到行中。

还有一件事要注意,我只是设置“disableHoverListener”props来禁用 tooltip 。还有其他props - "disableFocusListener" & "disableTouchListener" ,如果你想使用这些。更多信息在这里

希望这对你有用。如果您对代码有任何疑问,请告诉我。

我今天遇到了同样的问题,@vijay-menon 的回答非常有帮助。这是一个简单的独立组件,用于同一件事:

import React, { Component } from 'react';
import Tooltip from '@material-ui/core/Tooltip';

class OverflowTip extends Component {
    constructor(props) {
        super(props);
        this.state = {
            overflowed: false
        };
        this.textElement = React.createRef();
    }

    componentDidMount () {
        this.setState({
            isOverflowed: this.textElement.current.scrollWidth > this.textElement.current.clientWidth
        });
    }

    render () {
        const { isOverflowed } = this.state;
        return (
            <Tooltip
                title={this.props.children}
                disableHoverListener={!isOverflowed}>
                <div
                    ref={this.textElement}
                    style={{
                        whiteSpace: 'nowrap',
                        overflow: 'hidden',
                        textOverflow: 'ellipsis'
                    }}>
                    {this.props.children}
                </div>
            </Tooltip>
        );
    }
}

用法示例:

<OverflowTip>
      some long text here that may get truncated based on space
</OverflowTip>

一个麻烦是如果元素的空间在页面中动态变化(例如页面调整大小或动态 DOM 变化),它不会确认新空间并重新计算它是否溢出。

其他工具提示库(如 Tippy)有一个方法,当尝试打开工具提示时会触发该方法这是进行溢出检查的理想场所,因为它始终有效,无论文本元素的 DOM 宽度是否已更改。不幸的是,使用 Material UI 提供的 API 来做到这一点比较麻烦。