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