【问题标题】:Show more based on height in React在 React 中根据高度显示更多
【发布时间】:2021-09-27 16:32:11
【问题描述】:

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

请在此处检查我的代码框 CLICK HERE

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

【问题讨论】:

    标签: javascript html css reactjs styled-components


    【解决方案1】:

    由于您使用的是styled-components,因此我为它找到了一个很棒的实用程序包:polished.js

    您会寻找ellipsis 实用程序。

    省略号

    用省略号表示截断文本的 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>
      );
    };
    

    您似乎在另一个答案中提到您不想添加任何新的依赖项,因此这是通过 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;
        `}
    `;
    

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

    【讨论】:

    • 嗨@Drew Reese。如果文本很少,你怎么能隐藏Show more...?如果文本很少,显示Show more 将毫无意义。谢谢。
    • @Joseph 我发现了一些关于测试渲染内容宽度以计算是否发生溢出的 SO 帖子:stackoverflow.com/questions/64689074/…stackoverflow.com/questions/7738117/…。 jquery 的答案似乎很有希望,但将 jquery 与 React 混合通常不是一个好主意,但我认为在这种情况下它可能没问题,因为 jquery 没有用于更新 React 正在呈现的任何内容。 (我尝试将逻辑转换为 React,接近了)。
    • @Joseph 有时间我会多做一些。
    • 嗨,德鲁,可以帮我吗?谢谢你。 stackoverflow.com/questions/68902859/shorten-imports-in-react
    【解决方案2】:

    window.innerHeight &lt; 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>
      );
    };
    

    更新:

    由于您想获取行数,您可能需要使用this answer 中的这个逻辑来计算它:

    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来计算样式。

    Code Sandbox using window.innerHeight

    Code Sandbox based on number of lines

    【讨论】:

    • 这不是我想要的。我想修改它不应该计算字符数的功能,我希望它基于行数。在移动设备上可能有几行,但在台式机/笔记本电脑上可能只有几行,这就是原因。
    • 逻辑就在那里。将文本保存在状态中并根据您的规则进行修改。使用useEffect,这样您就可以获得对HTMLDivElement 的引用。
    • @Joseph,发布了更新的代码框。花了一些时间。幸运的是,我目前无事可做。 ;)
    • 您可能需要在窗口的resize 上添加一个侦听器,但您自己负责。
    猜你喜欢
    • 1970-01-01
    • 2012-01-24
    • 2016-10-19
    • 2018-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 2015-06-20
    相关资源
    最近更新 更多