背景
在平时的业务场景中,为了提升用户体验,经常会使用固定宽度,超出显示…的css样式。但是每次都写一次,比较麻烦,为了更好的摸鱼,所以把Ellipsis组件抽离出来。
先捋一下要实现的功能:
- 固定宽度,超出显示…
- 鼠标
hover
上去,能看到全部 - 支持多行显示…
- 考虑
resize
场景
思路
计算要渲染文字的宽度,如果宽度超出,就显示…
这里的问题是,如何计算文字的宽度呢?
- 可以先把文字在看不见的地方先渲染出来,获取到实际宽度,然后再去比较
- 直接给容器设置
overflow:hidden
,然后比较scrollWidth
跟clientWidth
的值
这里我用的是第二种。
import React, { FC, useCallback, useLayoutEffect, useRef, useState } from 'react'; import { Tooltip } from 'antd'; import debounce from 'lodash/debounce'; import useDimensions from 'react-cool-dimensions'; import { TooltipProps } from 'antd/lib'; interface EllipsisProps { line?: number style?: React.CSSProperties children?: React.ReactElement } const Ellipsis: FC<EllipsisProps & TooltipProps> = (props) => { const { children, line = 1, style: currentStyle = {}, ...other } = props; const wrapper = useRef<HTMLElement>(); const [showPopover, setShowPopover] = useState(false); // 先设置overflow: 'hidden', 这样超出了才能进行比较 const defaultStyle: React.CSSProperties = line === 1 ? { display: 'block', maxWidth: '100%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', ...currentStyle } : { overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitBoxOrient: 'vertical', WebkitLineClamp: line, ...currentStyle } const validShowPopover = () => { // 当line为1的时候,比较width // 否则,比较height const { scrollWidth = 0, clientWidth = 0, scrollHeight = 0, clientHeight = 0 } = wrapper.current as HTMLElement || {}; setShowPopover(scrollWidth > clientWidth || scrollHeight > clientHeight) } const debounceMesaure = useCallback(debounce(() => { validShowPopover(); }, 200), [validShowPopover]); // 支持resize const { observe } = useDimensions({ onResize: debounceMesaure, }); useEffect(() => { validShowPopover(); }, []); const renderChildren = () => { return React.cloneElement(children, { style: defaultStyle, ref: (element: HTMLElement | undefined) => { observe(element); wrapper.current = element; }, }) } // 基于ant的Tooltip组件 if (showPopover) { return <Tooltip {...other}>{renderChildren()}</Tooltip> } return renderChildren(); } export default Ellipsis
使用
Ellipsis组件的children必须是一个html元素标签
如果要渲染的元素没有给定宽度的话,需要手动向Ellipsis组件传一个width参数
import Ellipsis from './Ellipsis'; const EllipsisPage = () => { return <div> <Ellipsis style={{ width: 200 }} title={text} line={2}> <span>{text}</span> </Ellipsis> </div> } export default EllipsisPage;
如果要渲染的元素已经有指定的宽度,则不需要
import Ellipsis from './Ellipsis'; const EllipsisPage = () => { return <div> <div style={{ width: 200 }}> <Ellipsis title={text} line={1}> <span>{text}</span> </Ellipsis> </div> </div> } export default EllipsisPage;
到此这篇关于浅析react里面如何封装一个通用的Ellipsis组件的文章就介绍到这了,更多相关react封装Ellipsis组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
来源链接:https://www.jb51.net/javascript/332270ibh.htm
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容