【问题标题】:How to display a button only if text overflows仅当文本溢出时如何显示按钮
【发布时间】:2021-09-06 06:56:32
【问题描述】:
我有一个组件需要在文本溢出时显示一个按钮。
目前我将text-overflow 设置为ellipsis 并希望在此之后显示一个按钮。
这变得很复杂,因为没有允许的固定字符数或特定大小。
无论如何,我如何使用 React 或 SCSS 进行检查?
这是我目前拥有的示例:
const content = [
'short string. No button should be displayed.',
'Long string, please display button! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
]
const RenderString = ({content}) => {
return (
<div style={{ border: '1px solid blue' }}>
<div className='limited-space'>
{content}
</div>
<button>You should only see me if text is too long</button>
</div>
)
}
const App = () => {
return (
<div>
{content.map((c, index) => <RenderString key={index} content={c}/>)}
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
.limited-space {
margin: 10px;
padding: 10px;
width: 400px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border: 1px red solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
【问题讨论】:
标签:
javascript
css
reactjs
sass
【解决方案1】:
const content = [
'short string. No button should be displayed.',
'Long string, please display button! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
]
const isOverflow = (e) => {
return e.offsetWidth < e.scrollWidth
}
const RenderString = ({content}) => {
const textContainerRef = React.useRef()
const [showButton, setShowButton] = React.useState(false);
// When component renders
React.useEffect(() => {
setShowButton(isOverflow(textContainerRef.current))
}, [])
return (
<div style={{ border: '1px solid blue' }} >
<div className='limited-space' ref={textContainerRef} >
{content}
</div>
{showButton && <button>You should only see me if text is too long</button> }
</div>
)
}
const App = () => {
return (
<div>
{content.map((c, index) => <RenderString key={index} content={c}/>)}
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
.limited-space {
margin: 10px;
padding: 10px;
width: 400px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border: 1px red solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
【解决方案2】:
尝试以下方法:
const content = [
'short string. No button should be displayed.',
'Long string, please display button! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
];
const RenderString = ({content}) => {
const ref = React.useRef(null);
const [displayButton, setDisplayButton] = React.useState(false);
React.useLayoutEffect(() => {
const container = ref.current.getBoundingClientRect();
const text = ref.current.firstChild.getBoundingClientRect();
setDisplayButton(text.width > container.width);
}, []);
return (
<div style={{border: '1px solid blue'}}>
<div ref={ref} className='limited-space'>
<span>{content}</span>
</div>
{
displayButton ? <button>You should only see me if text is too long</button> : null
}
</div>
);
};
const App = () => {
return (
<div>
{content.map((c, index) => <RenderString key={index} content={c}/>)}
</div>
)
};
ReactDOM.render(
<App />,
document.getElementById('app')
);
.limited-space {
margin: 10px;
padding: 10px;
width: 400px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border: 1px red solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="app"></div>
【解决方案3】:
来源:this answer
const content = [
'short string. No button should be displayed.',
'Long string, please display button! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
]
const RenderString = ({content}) => {
const [isOverflowing, setIsOverflowing] = React.useState(false);
const widthRef = React.useRef(null);
React.useEffect(() => {
const el = widthRef.current;
if(el.offsetWidth < el.scrollWidth){
setIsOverflowing(true);
}
}, []);
return (
<div style={{ border: '1px solid blue' }}>
<div className='limited-space' ref={widthRef}>
{content}
</div>
{isOverflowing ? <button>You should only see me if text is too long</button> : null }
</div>
)
}
const App = () => {
return (
<div>
{content.map((c, index) => <RenderString key={index} content={c}/>)}
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
.limited-space {
margin: 10px;
padding: 10px;
width: 400px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border: 1px red solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>