React列表中实现文案多行收起展开的功能


css实现

在我们平时的业务开发中经常会用到文案超出只有收起,点击在展示全部文案;通常的使用时使用css来实现

display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;

效果如下:

使用css实现时只能做多行的省略,也没法根据文字去添加定制化的按钮去实现展开收起的功能,这个只是适合特定要求不是很高的场合下使用。

 

字符串截取

另一种方法是使用字符串截取的方案

_renderContent = item => { const { content, id } = item; if (content.length > 69) { return ( <div> <div ref={id} className="content"> {content.slice(0, 69)} </div> <div className="content-btn" ref={id + 'btn'} onClick={() => { this.handleContent(item); }}> 全文 </div> </div> ); } else { return <div className="content">{content}</div>; } }; 

展示效果:

弊端:数字、中文字符和引文字符的宽度是不一样的,在使用字符串截取是很容易出现如上的偏差,并且每个手机的分辨率不一样,字符渲染的宽度像素也是不同的,这样也会导致误差;所以字符串截取也不是一种很好的方案。

 

最终实现方案

话不多说直接上代码:content组件

js代码:

import react from 'react'; import cs from 'classnames'; import './style.scss'; export default class TextContainer extends React.Component { constructor(props) { super(props); this.state = { content: props.content, showAll: false, btnText: '全文', needHidden: false // 文字超出4行 需要隐藏 }; } /** * @description: 处理content文案的点击展开收起 * @return: null */ handleContent = e => { e.stopPropagation(); let { showAll } = this.state; this.setState({ showAll: !showAll }); }; // 判断文本超出行数 isElementCollision = (ele, rowCount = 4, cssStyles, removeChild) => { if (!ele) { return false; } const clonedNode = ele.cloneNode(true); // 给clone的dom增加样式 clonedNode.style.overflow = 'visible'; clonedNode.style.display = 'inline-block'; clonedNode.style.width = 'auto'; clonedNode.style.whiteSpace = 'nowrap'; clonedNode.style.visibility = 'hidden'; // 将传入的css字体样式赋值 if (cssStyles) { Object.keys(cssStyles).forEach(item => { clonedNode.style[item] = cssStyles[item]; }); } // 给clone的dom增加id属性 let _time = new Date().getTime(); const containerID = 'collision_node_id_' + _time; clonedNode.setAttribute('id', containerID); let tmpNode = document.getElementById(containerID); let newNode = clonedNode; if (tmpNode) { document.body.replaceChild(clonedNode, tmpNode); } else { newNode = document.body.appendChild(clonedNode); } // 新增的dom宽度与原dom的宽度*限制行数做对比 const differ = newNode.offsetWidth - ele.offsetWidth * rowCount + 40; // console.log(differ, 'differ'); if (removeChild) { document.body.removeChild(newNode); } return differ > 0; }; componentDidMount = () => { const cssStyles = { fontSize: '0.9375rem', fontWeight: '400', lineHeight: '1.5625rem' }; // console.log(this.isElementCollision(this.refs['content'], 4, cssStyles, true)); let needHidden = this.isElementCollision(this.refs['content'], 4, cssStyles, true); this.setState({ needHidden }); }; render() { let { content, needHidden, showAll } = this.state; let { headerText } = this.props; return ( <div> <div ref={'content'} className={cs('content', { 'hidden-text': !showAll && needHidden })}> {headerText ? headerText() : null} {content} </div> {needHidden && ( <div className="content-btn" onClick={e => { this.handleContent(e); }}> {!showAll ? '全文' : '收起'} </div> )} </div> ); } }

css代码:

$baseFontSize:32px !default; // pixels to rems @function pxToRem($px) { @return $px / $baseFontSize * 1rem; } .content { font-size: pxToRem(30px); font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: rgba(0, 0, 0, 1); line-height: pxToRem(50px); } .hidden-text { display: -webkit-box; -webkit-line-clamp: 3; /*! autoprefixer: off */ -webkit-box-orient: vertical; /* autoprefixer: on */ overflow: hidden; } .content-btn { font-size: pxToRem(28px); font-family: PingFangSC-Regular, PingFang SC; font-weight: 600; color: rgba(162, 116, 56, 1); line-height: pxToRem(48px); margin-top: pxToRem(10px); }

引用:

import TextContainer from '@/textContainer'; _renderContent = item => { const { content, id } = item; return <TextContainer content={content} />; };

效果:

豌豆资源搜索网站https://55wd.com 电脑刺绣绣花厂 ttp://www.szhdn.com


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM