基本上我希望能够检测到react组件是否有溢出的子组件。就像在这个问题中一样。我发现使用 ReactDOM 可以做同样的事情,但是我不能/不应该使用 ReactDOM。我在建议的替代方案中没有看到任何内容ref
,这是等效的。
所以我需要知道的是,在这些条件下是否有可能检测到react组件内的溢出。同样,是否有可能检测到宽度?
基本上我希望能够检测到react组件是否有溢出的子组件。就像在这个问题中一样。我发现使用 ReactDOM 可以做同样的事情,但是我不能/不应该使用 ReactDOM。我在建议的替代方案中没有看到任何内容ref
,这是等效的。
所以我需要知道的是,在这些条件下是否有可能检测到react组件内的溢出。同样,是否有可能检测到宽度?
除了@jered 的出色回答之外,我还想提到一个限定符,即如果 ref直接放置在 DOM element 上,则 ref 只会返回一个可以直接访问常规 DOM 元素的各种属性的元素。也就是说,它不会以这种方式使用Components。
所以如果你像我一样并且有以下几点:
var MyComponent = React.createClass({
render: function(){
return <SomeComponent id="my-component" ref={(el) => {this.element = el}}/>
}
})
并且当您尝试访问this.element
(可能在componentDidMount
或 中componentDidUpdate
)的DOM 属性并且您没有看到所述属性时,以下可能是适合您的替代方案
var MyComponent = React.createClass({
render: function(){
return <div ref={(el) => {this.element = el}}>
<SomeComponent id="my-component"/>
</div>
}
})
现在您可以执行以下操作:
componentDidUpdate() {
const element = this.element;
// Things involving accessing DOM properties on element
// In the case of what this question actually asks:
const hasOverflowingChildren = element.offsetHeight < element.scrollHeight ||
element.offsetWidth < element.scrollWidth;
},
@Jemar Jones 提出的解决方案的实现:
export default class OverflowText extends Component {
constructor(props) {
super(props);
this.state = {
overflowActive: false
};
}
isEllipsisActive(e) {
return e.offsetHeight < e.scrollHeight || e.offsetWidth < e.scrollWidth;
}
componentDidMount() {
this.setState({ overflowActive: this.isEllipsisActive(this.span) });
}
render() {
return (
<div
style={{
width: "145px",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
overflow: "hidden"
}}
ref={ref => (this.span = ref)}
>
<div>{"Triggered: " + this.state.overflowActive}</div>
<span>This is a long text that activates ellipsis</span>
</div>
);
}
}
是的,您可以使用ref
.
ref
在官方文档中阅读更多关于工作原理的信息:https : //facebook.github.io/react/docs/refs-and-the-dom.html
基本上,ref
只是在组件第一次呈现时运行的回调,紧接在componentDidMount
调用之前。回调中的参数是调用该ref
函数的 DOM 元素。所以如果你有这样的事情:
var MyComponent = React.createClass({
render: function(){
return <div id="my-component" ref={(el) => {this.domElement = el}}>Hello World</div>
}
})
当MyComponent
坐骑,它会调用该ref
函数集this.domElement
的DOM元素#my-component
。
有了这个,使用类似的东西getBoundingClientRect()
在渲染后测量你的 DOM 元素并确定子元素是否溢出父元素是相当容易的:
https://jsbin.com/lexonoyamu/edit?js,console,output
请记住,在渲染DOM 元素之前无法测量它们的大小/溢出,因为根据定义,它们还不存在。在将其渲染到屏幕之前,您无法测量某物的宽度/高度。
使用 React 钩子也可以实现相同的效果:
您需要的第一件事是保存文本 open和overflow active 的布尔值的状态:
const [textOpen, setTextOpen] = useState(false);
const [overflowActive, setOverflowActive] = useState(false);
接下来,您需要对要检查是否溢出的元素进行引用:
const textRef = useRef();
<p ref={textRef}>
Some huuuuge text
</p>
接下来是一个检查元素是否溢出的函数:
function isOverflowActive(event) {
return event.offsetHeight < event.scrollHeight || e.offsetWidth < e.scrollWidth;
}
然后你需要一个 useEffect 钩子来检查上面的函数是否存在溢出:
useEffect(() => {
if (isOverflowActive(reviewTextRef.current)) {
setOverflowActive(true);
return;
}
setOverflowActive(false);
}, [isOverflowActive]);
现在有了这两个状态和一个检查溢出元素是否存在的函数,你可以有条件地渲染一些元素(例如显示更多按钮):
{!textOpen && !overflowActive ? null : (
<button>{textOpen ? 'Show less' : 'Show more'}</button>
)}