【react】文本内容超过一行,显示为单行省略,并且出现icon图标;点击此图标,可以进行展开或收起文本功能实现

需求:

  1. 多条数据展示,每条数据的文本内容不超过一行
  2. 文本内容为一行时,不显示 展开收起icon图标
  3. 文本超过一行时,内容单行省略,并且显示⬇️
  4. 点击图标,图标切换为收起按钮, ⬆️
// 后端返回数据
const data = [
    {
      name: '测试测试测试',
      time: '2022-07-06 18:50:08',
      remark:
        '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试',
    },
    {
      name: '测试测试测试',
      time: '2022-07-06 18:50:08',
      remark:
        '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试',
    },
    {
      name: '测试测试测试',
      time: '2022-07-06 18:50:08',
      remark:
        '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试',
    },
]

使用useEffect处理

// 监听文本的可视宽度(ref.current.clientWidth)和滚动宽度 (ref.current.scrollWidth)
const ref = useRef<HTMLDivElement>(null)
// 利用可视宽度和滚动宽度比较来判断是否显示此按钮

// 依赖数据长度以及刷新
useEffect(() => {
    if (data && !isLoading) {
      const dataObj = [...data]
      dataObj.map((item: { isShow: boolean }) => {
      // 为每一条数据添加isShow 来控制文本显示和按钮显示
        if (!item.isShow) {
          item.isShow = false
        }
      })
      mutate(dataObj) // mutate 重新请求数据
    }
  }, [data?.length, isLoading])

函数方法

 // 点击展示或收起数据
  const handlerChange = (val: number) => {
    const arr = [...data]
    arr.map((item: { isShow: boolean }, index: number) => {
      if (index === val) {
        item.isShow = !item.isShow
      }
    })
    mutate(arr) // mutate 重新请求数据
  }

数据渲染

// 数据渲染
 {data.map(
	 (item: { 
		  name: string 
		  time: string 
		  remark: string 
		  isShow: boolean
		    },
		    index: number
	  ) => (
	    <Main rows={!item.isShow ? 1 : 9999} key={index}>
	      <div className="point_title">
	        <div className="title_text">{item.name}</div>
	      </div>
	      <div className="point_time">
	        {item.time.replace(/-/g, '/')}
	      </div>
	      <div className="point_remark">
	        <div className="remark_text" ref={ref}>
	          {item.remark}
	        </div>
	        {(item.isShow ||
	          (ref.current &&
	            ref.current.clientWidth < ref.current.scrollWidth)) && (
	          <div
	            onClick={() => handlerChange(index)}
	            className="remark_icon"
	          >
	            {item.isShow ? (
	              <ArrowUp className="icon" />
	            ) : (
	              <ArrowDown className="icon" />
	            )}
	          </div>
	        )}
	      </div>
	    </Main>
	 )
)}

样式渲染

const Main = styled.div<{
  rows: number
}>`
  margin: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid #ededed;
  .icon {
    width: 14px;
    height: 14px;
  }
  .point_title {
    display: flex;
    justify-content: space-between;
    .title_text {
      font-family: 'PingFangSC-Medium';
      font-size: 14px;
      color: #262626;
      line-height: 22px;
      font-weight: 500;
      flex: 1 1;
    }
  }
  .point_time {
    margin-top: 4px;
    margin-bottom: 4px;
    font-family: 'PingFangSC-Regular';
    font-size: 12px;
    color: #8c8c8c;
    line-height: 20px;
    font-weight: 400;
    height: 20px;
  }
  .point_remark {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: #8c8c8c;
    line-height: 20px;
    font-weight: 400;
    .remark_text {
      width: 313px;
      ${(p) => MultiLineOmission(p.rows)}; // 多行省略
    }
    .remark_icon {
      display: flex;
      align-items: center;
    }
  }
`
export { Main }

多行省略的实现

// 多行省略
const MultiLineOmission = (line = 3) => css`
  display: ${() => line !== 1 && '-webkit-box'};
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: ${() => line};
  -webkit-box-orient: vertical;
  word-break: break-all;
  white-space: ${() => line === 1 && 'nowrap'};
`
export { MultiLineOmission }

总结:

  1. 注意是每一条数据,因此需要给每一条数据添加 isShow
  2. 点击时传入每一条数据的id值,如果没有id也可以使用index,将此条数据的item.isShow变为!item.isShow,然后进行重新刷新数据。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用CSS中的`overflow`属性来控制盒子内内容溢出时的表现,为了达到你想要的效果,可以将`overflow`属性设置为`hidden`,然后给盒子添加一个图标,并通过JavaScript来监听图标点击事件,当图标点击时,将盒子的`overflow`属性设置为`auto`,这样就可以出现纵向滚动条了。 下面是一个简单的示例代码: HTML代码: ```html <div class="box"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec condimentum semper lobortis. Nam euismod tristique dolor, ac dictum mauris lacinia nec. Vestibulum commodo urna at nulla molestie, vel interdum lectus mollis. Sed auctor turpis vel enim mattis, id tempor sapien vehicula. Nullam eget leo id mauris dapibus eleifend et sit amet metus. Vivamus vitae nisl justo. Mauris bibendum, erat sed egestas viverra, urna enim commodo metus, in molestie libero arcu non mauris. Morbi euismod massa ac arcu suscipit, ut imperdiet mauris efficitur.</p> <img src="expand.png" class="expand-icon" alt="Expand Icon"> </div> ``` CSS代码: ```css .box { width: 200px; height: 100px; overflow: hidden; position: relative; } .expand-icon { position: absolute; bottom: 0; right: 0; cursor: pointer; } ``` JavaScript代码: ```javascript const box = document.querySelector('.box'); const expandIcon = document.querySelector('.expand-icon'); expandIcon.addEventListener('click', () => { box.style.overflow = 'auto'; }); ``` 这样,当用户点击图标时,盒子内容就可以纵向滚动了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值