淺析react里面如何封裝一個通用的Ellipsis組件
背景
在平時的業(yè)務場景中,為了提升用戶體驗,經常會使用固定寬度,超出顯示...的css樣式。但是每次都寫一次,比較麻煩,為了更好的摸魚,所以把Ellipsis組件抽離出來。
先捋一下要實現(xiàn)的功能:
- 固定寬度,超出顯示...
- 鼠標
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參數(shù)
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組件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決React報錯Property 'X' does not 
這篇文章主要為大家介紹了解決React報錯Property 'X' does not exist on type 'HTMLElement',有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12React Native 搭建開發(fā)環(huán)境的方法步驟
本篇文章主要介紹了React Native 搭建開發(fā)環(huán)境的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10React State狀態(tài)與生命周期的實現(xiàn)方法
這篇文章主要介紹了React State狀態(tài)與生命周期的實現(xiàn)方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03