Jem*_*nes 3 javascript reactjs
基本上我希望能够检测反应组件是否有溢出的子项.就像在这个问题中一样.我发现使用ReactDOM可以做同样的事情,但我不能/不应该使用ReactDOM.我没有看到建议的替代方案ref,这是等效的.
所以我需要知道的是,在这些条件下是否有可能检测到反应组分内的溢出.同样,是否可以检测宽度?
Jem*_*nes 11
除了@ jered的优秀答案之外,我还想提一下限定符,如果ref 直接放在DOM元素上,ref只会返回一个直接访问常规DOM元素的各种属性的元素.也就是说,它不会以这种方式与组件一起运行.
所以,如果你像我一样,并拥有以下内容:
var MyComponent = React.createClass({
render: function(){
return <SomeComponent id="my-component" ref={(el) => {this.element = el}}/>
}
})
Run Code Online (Sandbox Code Playgroud)
当您尝试访问this.element(可能在componentDidMount或中componentDidUpdate)的DOM属性并且您没有看到所述属性时,以下可能是适合您的替代方案
var MyComponent = React.createClass({
render: function(){
return <div ref={(el) => {this.element = el}}>
<SomeComponent id="my-component"/>
</div>
}
})
Run Code Online (Sandbox Code Playgroud)
现在您可以执行以下操作:
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;
},
Run Code Online (Sandbox Code Playgroud)
Rin*_*nor 11
@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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 11
我需要在 React TypeScript 中实现这一点,因此这里是使用 React Hooks 在 TypeScript 中更新的解决方案。如果至少有 4 行文本,此解决方案将返回 true。
我们声明必要的状态变量:
const [overflowActive, setOverflowActive] = useState<boolean>(false);
const [showMore, setShowMore] = useState<boolean>(false);
Run Code Online (Sandbox Code Playgroud)
我们使用以下方法声明必要的引用useRef:
const overflowingText = useRef<HTMLSpanElement | null>(null);
Run Code Online (Sandbox Code Playgroud)
我们创建一个检查溢出的函数:
const checkOverflow = (textContainer: HTMLSpanElement | null): boolean => {
if (textContainer)
return (
textContainer.offsetHeight < textContainer.scrollHeight || textContainer.offsetWidth < textContainer.scrollWidth
);
return false;
};
Run Code Online (Sandbox Code Playgroud)
让我们构建一个在更改useEffect时调用的函数overflowActive,并检查当前的 ref 对象以确定该对象是否溢出:
useEffect(() => {
if (checkOverflow(overflowingText.current)) {
setOverflowActive(true);
return;
}
setOverflowActive(false);
}, [overflowActive]);
Run Code Online (Sandbox Code Playgroud)
在组件的 return 语句中,我们需要将 ref 绑定到适当的元素。我正在使用Material UI耦合,styled-components因此本示例中的元素将是StyledTypography:
<StyledTypography ref={overflowingText}>{message}</StyledTypography>
Run Code Online (Sandbox Code Playgroud)
设计组件的样式styled-components:
const StyledTypography = styled(Typography)({
display: '-webkit-box',
'-webkit-line-clamp': '4',
'-webkit-box-orient': 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis',
});
Run Code Online (Sandbox Code Playgroud)
小智 9
使用 React hooks 也可以实现同样的效果:
您需要的第一件事是保存文本打开和溢出活动的布尔值的状态:
const [textOpen, setTextOpen] = useState(false);
const [overflowActive, setOverflowActive] = useState(false);
Run Code Online (Sandbox Code Playgroud)
接下来,您需要对要检查溢出的元素进行引用:
const textRef = useRef();
<p ref={textRef}>
Some huuuuge text
</p>
Run Code Online (Sandbox Code Playgroud)
接下来是一个检查元素是否溢出的函数:
function isOverflowActive(event) {
return event.offsetHeight < event.scrollHeight || event.offsetWidth < event.scrollWidth;
}
Run Code Online (Sandbox Code Playgroud)
然后你需要一个 useEffect 钩子来检查上述函数是否存在溢出:
useEffect(() => {
if (isOverflowActive(textRef.current)) {
setOverflowActive(true);
return;
}
setOverflowActive(false);
}, [isOverflowActive]);
Run Code Online (Sandbox Code Playgroud)
现在有了这两种状态和一个检查溢出元素是否存在的函数,您可以有条件地渲染某些元素(例如,显示更多按钮):
{!textOpen && !overflowActive ? null : (
<button>{textOpen ? 'Show less' : 'Show more'}</button>
)}
Run Code Online (Sandbox Code Playgroud)
是的,您可以使用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>
}
})
Run Code Online (Sandbox Code Playgroud)
当MyComponent坐骑,它会调用该ref函数集this.domElement的DOM元素#my-component。
有了它,使用诸如getBoundingClientRect()DOM元素渲染后确定子元素是否溢出父元素的方法就很容易了:
https://jsbin.com/lexonoyamu/edit?js,控制台,输出
请记住,在定义DOM元素之前,无法测量它们的大小/溢出,因为根据定义,它们尚不存在。您无法测量某物的宽度/高度,除非将其渲染到屏幕上。
| 归档时间: |
|
| 查看次数: |
10467 次 |
| 最近记录: |