css - 在两行文本后添加省略号和工具提示 - React
问题描述
是否可以创建一个 React 组件,它可以在两行之后添加省略号并仅在文本被换行时才显示工具提示?
我尝试使用“noWrap”属性和其他 CSS 自定义 Material UI 的 Typography 组件,但失败了。
解决方案
这个问题主要有两个方面:
- 根据垂直溢出显示文本溢出的省略号,以便允许多行但不是无限的
- 在这种情况下检测垂直溢出并包含工具提示功能
我不相信 FrankerZ 的解决方案会显示省略号。据我所知,text-overflow: ellipsis
仅适用于需要将文本限制为单行的水平溢出。
我在这里找到了一个在垂直溢出上进行省略的解决方案,但是一旦你开始将它包装在 Material UI 组件(例如 ListItem)中,它可能需要进行重大调整,这会带来额外的 CSS,并且它可能会变得足够复杂以至于不值得. 该解决方案的效果是在每行文本的末尾为省略号保留空间,这似乎并不理想。这个问题似乎还有其他一些解决方案,但我自己没有使用过任何一个(包括今天以外的这个)。
第二部分(检测溢出)似乎更直接,由divRef.current.scrollHeight > divRef.current.offsetHeight
. 我通过找到许多关于根据宽度进行类似条件的参考来得出这个解决方案。在处理这个答案时,我没有在今天之外亲自使用过这种技术,所以有更深入的 CSS 专业知识的人可能会说“你永远不应该这样做,因为......”,但它似乎有效(我没有做过任何重要的浏览器测试——仅在 Chrome 上尝试过)。
为了语法方便,我在示例中使用了钩子,因此如果您不使用 alpha,则需要将状态、引用和效果工作转换为相应的类对应项。这目前也没有处理调整窗口大小,这需要重新评估工具提示是否应该生效。有了这些警告,希望这将为您提供一些可行的解决方案。
这是代码:
import React, { useRef, useState, useEffect } from "react";
import ReactDOM from "react-dom";
import Tooltip from "@material-ui/core/Tooltip";
import { withStyles } from "@material-ui/core/styles";
/*
CSS from http://hackingui.com/front-end/a-pure-css-solution-for-multiline-text-truncation/
Additional syntax help from https://stackoverflow.com/questions/40965977/cant-target-before-pseudo-selector-in-jss
*/
const styles = theme => ({
listItem: {
maxWidth: "20rem",
overflow: "hidden",
position: "relative",
lineHeight: "1.2em",
maxHeight: "2.4em",
textAlign: "justify",
marginRight: "-1em",
paddingRight: "1em",
borderBottom: "1px solid",
marginBottom: "0.5em",
"&&:before": {
content: '"..."',
position: "absolute",
right: 0,
bottom: 0
},
"&&:after": {
content: '""',
position: "absolute",
right: 0,
width: "1em",
height: "1em",
marginTop: "0.2em",
background: "white"
}
}
});
const data = [
"Some short text",
"Some text that is a little bit longer",
"Some text that will need to wrap but still fits on two lines",
"Some text that will overflow because it is more than just two lines worth when the maxWidth is set at 20rem.",
"A massive range of hammer drill machines and rotary hammers for SDS-plus accessory tools, designed for higher performance drilling and longer life - for easy drilling in concrete and other materials."
];
const TooltipDiv = props => {
const divRef = useRef(null);
const [allowTooltip, setAllowTooltip] = useState(false);
useEffect(() => {
if (
!allowTooltip &&
divRef.current.scrollHeight > divRef.current.offsetHeight
) {
setAllowTooltip(true);
}
}, []);
if (allowTooltip) {
return (
<Tooltip title={props.text}>
<div ref={divRef} className={props.className}>
{props.text}
</div>
</Tooltip>
);
}
return (
<div ref={divRef} className={props.className}>
{props.text}
</div>
);
};
function App(props) {
return (
<>
{data.map(text => {
return (
<>
<TooltipDiv text={text} className={props.classes.listItem} />
</>
);
})}
</>
);
}
const StyledApp = withStyles(styles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<StyledApp />, rootElement);
你可以在这里看到它的实际效果:
推荐阅读
- javascript - 在 Nextjs 中扩展 React.FC 的默认行为
- reactjs - 使用 react-test-renderer 和 typescript 测试 MUI 菜单组件
- python-3.x - 韦尔奇变换以保持尺寸
- api - 如何使用 Dio 或 http 在 Flutter 中通过 GET 请求发送参数
- c# - asp 页面 url 为空
- python - 为什么使用 BeautifulSoup 找不到和提取 br 标签
- java - 无论我对代码做什么,nextInt() 中的 NoSuchElementException
- python - 如何连接numpy数组的动态切片?
- javascript - 在jquery中找到选定的值
- laravel - 在laravel中的db中显示summernote中的图像