我正在 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 中使用这些值,我们需要使用 ref
和 useLayoutEffect
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/