reactjs - 如果文本超过一定数量的行,如何在 React 中截断文本并显示“阅读更多”按钮?

标签 reactjs tailwind-css

我正在 React 中构建一个 Notes 应用程序,并将注释存储在 Firestore 中。如果我从 Firestore 读取的内容超过三行,我想显示“阅读更多”按钮。如果没有,那么我不想显示“阅读更多”按钮,

还使用 Tailwind 进行样式设置,我知道他们有一个线路营地插件和名为“truncate”的类,但我不知道如何使用条件渲染按钮来实现它。因此,任何有关如何实现这一点的帮助将不胜感激。这是我需要截断的文本的代码。

<div>
   <p className="break-words text-xl">{note?.noteContent}</p>
</div>

最佳答案

使用CSS(或Tailwind)截断到特定行是一个很好的方法。然后,您需要使用 JavaScript 来检测您的文本是否已被截断,以便您可以决定显示/隐藏“阅读更多”按钮。这可以通过将元素的 scrollHeight 与其 offsetHeight 进行比较来完成。

  • scrollHeight 测量元素内容的高度,包括因溢出而隐藏的任何内容 ( MDN link )
  • offsetHeight 测量元素的渲染高度,不包括因溢出而隐藏的任何内容 ( MDN link )

因此,如果 scrollHeight 大于 offsetHeight,我们就知道我们的元素存在一些溢出。在这种情况下,我们的文本已被截断。要在 React 中使用这些值,我们需要使用 refuseLayoutEffect Hook 。

完整示例代码

这假设您只是想要一个“阅读更多”按钮。我将提供另一个带有“少读”选项的示例。

import React, { useState, useLayoutEffect } from 'react'

const useTruncatedElement = ({ ref }) => {
  const [isTruncated, setIsTruncated] = useState(false);
  const [isReadingMore, setIsReadingMore] = useState(false);

  useLayoutEffect(() => {
    const { offsetHeight, scrollHeight } = ref.current || {};

    if (offsetHeight && scrollHeight && offsetHeight < scrollHeight) {
      setIsTruncated(true);
    } else {
      setIsTruncated(false);
    }
  }, [ref]);

  return {
    isTruncated,
    isReadingMore,
    setIsReadingMore,
  };
};

export default function Note() {
  const ref = React.useRef(null);
  const { isTruncated, isReadingMore, setIsReadingMore } = useTruncatedElement({
    ref,
  });

  // Code to get your note content...

  return (
    <div>
      <p ref={ref} className={`break-words text-xl ${!isReadingMore && 'line-clamp-3'}`}>
        {note?.noteContent}
      </p>
      {isTruncated && !isReadingMore && (
        <button onClick={() => setIsReadingMore(true)}>
          Read more
        </button>
      )}
    </div>
  )
}

代码演练

如果您的段落已被截断,useTruncatedElement 钩子(Hook)就会起作用,如上所述。它还返回一些状态来确定“阅读更多”按钮是否已被单击。这样我们就可以通过删除 line-clamp-3 类来扩展文本,并在单击按钮后隐藏按钮(或将文本更改为“少读”)。

Tailwind 的线夹插件

该插件使用 line-clamp-{n} 形式的一个类来处理截断。它将以下 CSS 添加到元素(如果您不使用 tailwind,则可以添加):

.line-clamp-{n} {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: {n};
}

安装插件:

npm install -D @tailwindcss/line-clamp

yarn 添加-D @tailwindcss/line-clamp

然后将其添加到 tailwind.config.cjs 文件中的插件数组中:

module.exports = {
  ...
  plugins: [require("@tailwindcss/line-clamp")],
};

显示更多/显示更少

如果您想要一个切换,以便用户可以在展开文本后再次截断文本(一种显示更多/显示更少的场景),那么您可以从 Hook 返回切换函数:

import React, { useState, useLayoutEffect } from 'react'

const useTruncatedElement = ({ ref }) => {
  const [isTruncated, setIsTruncated] = useState(false);
  const [isShowingMore, setIsShowingMore] = useState(false);

  useLayoutEffect(() => {
    const { offsetHeight, scrollHeight } = ref.current || {};

    if (offsetHeight && scrollHeight && offsetHeight < scrollHeight) {
      setIsTruncated(true);
    } else {
      setIsTruncated(false);
    }
  }, [ref]);

  const toggleIsShowingMore = () => setIsShowingMore(prev => !prev);

  return {
    isTruncated,
    isShowingMore,
    toggleIsShowingMore,
  };
};

export default function Note() {
  const ref = React.useRef(null);
  const { isTruncated, isShowingMore, toggleIsShowingMore } = useTruncatedElement({
    ref,
  });

  // Code to get your note content...

  return (
    <div>
      <p ref={ref} className={`break-words text-xl ${!isShowingMore && 'line-clamp-3'}`}>
        {note?.noteContent}
      </p>
      {isTruncated && (
        <button onClick={toggleIsShowingMore}>
          {isShowingMore ? 'Show less' : 'Show more'}
        </button>
      )}
    </div>
  )
}

关于reactjs - 如果文本超过一定数量的行,如何在 React 中截断文本并显示“阅读更多”按钮?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74201658/

相关文章:

javascript - React hook 状态对于几个相同的事件具有不同的值

javascript - React Router 不渲染任何东西

reactjs - 路由不适用于使用 ReactJS 和 reach-router 的打包 Electron 应用程序

tailwind-css - Figma 中的 Tailwindcss

javascript - Onclick 不会在渲染点绑定(bind)变量的值

javascript - React - 获取输入

css - 顺风CSS : Can't use breakpoints for box-shadow

reactjs - 使用变量时 Tailwind 不工作(React.js)

tailwind-css - 紫杉顺风 css

html - Radix UI "Select"原语溢出屏幕