在 React 中根据身高显示更多内容

IT技术 javascript html css reactjs styled-components
2021-04-28 20:25:17

我已经成功地实现了更多/更少展示。我的问题是我想根据屏幕的行数或高度来实现它。我不希望它基于字符数,因为它在某些屏幕上看起来很糟糕。就像在大屏幕上有点切,而在小屏幕上太长了。

请在这里检查我的代码和框 点击这里

  <DescriptionText>
    {isShowMore ? text.slice(0, 300) : text}
  </DescriptionText>
  {text && text.length > 300 && (
    <ShowMoreText onClick={toggleReadMore}>
      {isShowMore ? "Show more..." : "Show less"}
    </ShowMoreText>
  )}
2个回答

由于您正在使用,styled-components我为它找到了一个很棒的实用程序包:Polish.js

您将寻找省略号实用程序。

省略

用省略号表示截断文本的 CSS。您可以选择在截断之前传递最大宽度和行数。

ellipsis(width: (string? | number?)?, lines: number): Styles

示例:显示更多时最多显示 3 行,否则显示为全文。

import { ellipsis } from 'polished';

...

const DescriptionText = styled.div`
  font-size: 14px;
  margin-top: 20px;
  margin-bottom: 20px;
  ${({ showMore }) => showMore && ellipsis(undefined, 3)}
`;

...

const Description = () => {
  const [isShowMore, setIsShowMore] = useState(true);
  const toggleReadMore = () => setIsShowMore(show => !show);

  return (
    <MainContainer>
      <TitleText>Description</TitleText>
      <DescriptionText showMore={isShowMore}>{text}</DescriptionText>
      <ShowMoreText onClick={toggleReadMore}>
        {isShowMore ? "Show more..." : "Show less"}
      </ShowMoreText>
    </MainContainer>
  );
};

在此处输入图片说明 在此处输入图片说明

编辑 show-more-based-on-height-in-react

您似乎在另一个答案中提到您不想添加任何新的依赖项,因此这里是通过该ellipsis实用程序应用的 CSS 尽管如此,polished如果可以的话,我仍然建议将其添加到您的项目中,因为它具有许多我发现相当无价的有用样式实用程序。

import styled, { css } from "styled-components";

const DescriptionText = styled.div`
  font-size: 14px;
  margin-top: 20px;
  margin-bottom: 20px;
  ${({ showMore }) =>
    showMore &&
    css`
      display: -webkit-box;
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: normal;
      word-wrap: normal;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 3;
    `}
`;

要处理不同的屏幕尺寸/响应能力,您可以使用媒体查询并指定您想要初始显示的不同行数。

怎么样window.innerHeight < minHeight这意味着您需要定义minHeight

const text = `Lorem ipsum .....`; //
let _shouldTruncate = null;
const minHeight = 750;
const Description = () => {
  const descTextEl = useRef(null);
  const [isShowMore, setIsShowMore] = useState(true);
  const toggleReadMore = () => {
    setIsShowMore(!isShowMore);
  };
  const [txtVal, setTxtVal] = useState(""); //save value to state
  //updates `txtVal` on change of `isShowMore`
  useEffect(() => {
    if (_shouldTruncate === null) {
      _shouldTruncate = window.innerHeight < minHeight;
    }
    setTxtVal(_shouldTruncate && isShowMore ? text.slice(0, 300) : text);
  }, [txtVal, isShowMore]);

  return (
    <MainContainer>
      <TitleText>Description</TitleText>
      <DescriptionText ref={descTextEl}>{txtVal}</DescriptionText>
      {_shouldTruncate && (
        <ShowMoreText onClick={toggleReadMore}>
          {isShowMore ? "Show more..." : "Show less"}
        </ShowMoreText>
      )}
    </MainContainer>
  );
};

更新:

由于您想获得行数,因此您可能需要使用此答案中的逻辑来计算它

function countLines() {
   var el = document.getElementById('content');
   var divHeight = el.offsetHeight
   var lineHeight = parseInt(el.style.lineHeight);
   //or use computed lineHeight: 
   //var lineHeight = document.defaultView.getComputedStyle(el, null).getPropertyValue("lineHeight");
   var lines = divHeight / lineHeight;
   alert("Lines: " + lines);
}

更新:

您需要导入ReactDom以计算样式。

代码沙箱使用 window.innerHeight

基于行数的代码沙箱