假设你的卡片组件是这样的
function Card({ name }) {
return (
<div className="card">
<div className="card__pic"></div>
<h3 className="card__name" ref={nameRef}>
{name}
</h3>
</div>
);
}
我们只需要包含名称的元素,即“card__name”。
- 访问“名称”元素。
要访问这个名称元素,我们必须使用useRef 钩子。以下是您将如何使用它。
function Card({ name }) {
const nameRef = useRef(null);
useEffect(() => {
// nameRef.current is accessible here
}, []);
return (
<div className="card">
<div className="card__pic"></div>
<h3 className="card__name" ref={nameRef}>
{name}
</h3>
</div>
);
}
我们必须将ref={refVariable} 传递给我们想要访问的元素。
refVariable 将在挂载后使用元素节点进行初始化,即我们可以在 useEffect 挂钩中使用它。
- 确定名称是否溢出。
现在我们有了元素,我们可以用它来检查里面的文本是否溢出。我创建了一个函数isTextOverflowingCard,我们将引用传递给我们在挂载后获得的元素。如果文本溢出则返回 true,否则返回 false。
function isTextOverflowingCard(textElement) {
if (textElement.scrollWidth > textElement.clientWidth) {
return true;
}
return false;
}
现在我们可以在 Card 内部使用这个函数,并根据它的返回值,有条件地添加一个类,该类将具有紧密的字母间距值。
function Card({ name }) {
const nameRef = useRef(null);
const [textOverflow, setTextOverflow] = useState(false);
useEffect(() => {
// nameRef.current is accessible here
setTextOverflow(isTextOverflowingCard(nameRef.current));
}, []);
return (
<div className="card">
<div className="card__pic"></div>
<h3 className={`card__name ${textOverflow ? 'card__name--tight-kerning' : ''}`} ref={nameRef}>
{name}
</h3>
</div>
);
}
在 CSS 中,
.card__name--tight-kerning {
letter-spacing: -2px;
}
可以将useEffect改成useLayoutEffect,更适合这种dom相关的计算和应用于ui。
参考资料:
- Detect if text has overflown
- useEffect vs useLayoutEffect
- https://reactjs.org/docs/hooks-reference.html#useref