You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React展开收起按钮需双击问题求助

React中“Read more/Read less”功能双击触发问题求助

我在React应用中实现“Read more/Read less”功能时遇到问题:按钮需要双击才能切换div中文本的显示/收起状态。网上有类似问题但找不到适配我场景的解决方案,我参考了YouTube教程,教程中只需单击即可实现,但不清楚自己哪里出错了。

以下是我当前的实现代码:

JS代码

function ReadMoreLess() {
    let more = document.querySelectorAll('.more');
    for (let i = 0; i < more.length; i++) {
      more[i].addEventListener('click',function(){
        more[i].parentNode.classList.toggle('active')
      })
    }
  }

JSX代码(组件return内)

<div className="containerNFT">
  <div className="card">
     <div className="content">
        <h3>Read More or Less</h3>
        <p>
        Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text 
        Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text 
        Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text  
        Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text 
        </p>
    </div>
    <button type="button" onClick={ReadMoreLess} className="more" title="Read"></button>
  </div>
</div>

CSS代码

.containerNFT {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  margin-left: 50px;
}

.containerNFT .card {
  position: relative;
  width: 600px;
  padding: 11px;
  margin: 11px;
  border: 20px solid #fff;
}

.containerNFT .card::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  border: 20px solid transparent;
  border-top: 20px solid #0066FF;
  border-right: 20px solid #0066FF;
}

.containerNFT .card.active::before {
  border-top: 20px solid #0133FF;
  border-right: 20px solid #0133FF;
}

.containerNFT .card .content {
  position: relative;
  height: 225px;
  overflow: hidden;
}

.containerNFT .card.active .content {
  height: auto;
}

.containerNFT .card .content::before {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100px;
  background: linear-gradient(transparent, #fff);
}

.containerNFT .card.active .content::before {
  display: none;
}

.containerNFT .card .content h3 {
  font-size: 0.75em;
  font-weight: 600;
  margin-bottom: 10px;
}

.containerNFT .card .content p {
  font-weight: 300;
}

.more {
  border-color: #0066FF;
}

.containerNFT .card .more {
  position: relative;
  padding: 10px 15px;
  background: #0066FF;
  border-radius: 8px;
  margin-top: 15px;
  display: inline-block;
  cursor: pointer;
  text-transform: uppercase;
  font-weight: 500;
  letter-spacing: 2px;
  font-size: 14px;
  color: #fff;
}

.containerNFT .card.active .more {
  background: #0133FF;
}

.containerNFT .card .more::before {
  content: 'Read more';
}

.containerNFT .card.active .more::before {
  content: 'Read less';
}

我觉得当前CSS写法过于复杂,但找不到用useState钩子实现文本部分隐藏(渐变透明)的合适示例,因此暂时希望保留现有CSS方案。我的最终目标是实现文本展开收起的渐变过渡效果(如图:文本渐变收起效果)。


问题原因及修复方案

问题根源

你当前的写法是在按钮点击时才去绑定点击事件:第一次点击按钮,执行ReadMoreLess函数,给按钮添加了click事件监听;第二次点击按钮,才会触发刚绑定的事件,切换active类。这就是需要双击的原因。

修复方案1:直接在点击事件中操作DOM(最小改动)

不需要循环绑定事件,直接在点击时通过事件对象获取按钮的父元素,切换类名:

function ReadMoreLess(e) {
  // e.target就是点击的按钮,直接取父元素切换active类
  e.target.parentNode.classList.toggle('active');
}

这样每次点击按钮都会直接触发类名切换,无需额外绑定事件,解决双击问题。

修复方案2:React式写法(使用useState管理状态)

既然是React应用,更推荐用React的状态管理代替原生DOM操作,同时保留你的渐变效果:

import { useState } from 'react';

function ReadMoreLessComponent() {
  const [isExpanded, setIsExpanded] = useState(false);

  const toggleExpand = () => {
    setIsExpanded(!isExpanded);
  };

  return (
    <div className="containerNFT">
      <div className={`card ${isExpanded ? 'active' : ''}`}>
        <div className="content">
          <h3>Read More or Less</h3>
          <p>
            Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text 
            Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text 
            Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text  
            Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text 
          </p>
        </div>
        <button type="button" onClick={toggleExpand} className="more" title="Read"></button>
      </div>
    </div>
  );
}

export default ReadMoreLessComponent;

这种写法完全符合React的状态管理逻辑,避免了原生DOM操作的潜在问题,同时你的CSS样式可以完全复用,渐变效果也能正常保留。

内容的提问来源于stack exchange,提问作者Dieter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 06:25:24