Reactjs 在react.js中加载DOM时回调
我希望在react.js组件的DOM元素(包括所有子节点)实际加载到页面并准备就绪时,在该组件上调用回调。具体来说,我有两个组件,我想渲染相同的大小,选择具有较大自然大小的组件的最大值Reactjs 在react.js中加载DOM时回调,reactjs,Reactjs,我希望在react.js组件的DOM元素(包括所有子节点)实际加载到页面并准备就绪时,在该组件上调用回调。具体来说,我有两个组件,我想渲染相同的大小,选择具有较大自然大小的组件的最大值 看起来componentDidMount并不是我真正想要的,因为每个组件只调用一次,但我希望在组件完成渲染时再次调用回调。我想我可以向顶级DOM元素添加一个onLoad事件,但我想这只适用于某些元素,比如和看起来像是componentDidMount和componentdiddupdate的组合将完成任务。第一个
看起来
componentDidMount
并不是我真正想要的,因为每个组件只调用一次,但我希望在组件完成渲染时再次调用回调。我想我可以向顶级DOM元素添加一个onLoad
事件,但我想这只适用于某些元素,比如
和
看起来像是componentDidMount
和componentdiddupdate
的组合将完成任务。第一个在初始渲染之后调用,当DOM可用时,第二个在任何后续渲染之后调用,一旦更新的DOM可用。在我的例子中,我让它们都委托给一个公共函数来做同样的事情。我将componentDidUpdate应用到表中,使所有列具有相同的高度。它的工作原理与jquery中的$(window.load()相同
例如:
在componentDidMount中添加onload侦听器
class Comp1 extends React.Component {
constructor(props) {
super(props);
this.handleLoad = this.handleLoad.bind(this);
}
componentDidMount() {
window.addEventListener('load', this.handleLoad);
}
componentWillUnmount() {
window.removeEventListener('load', this.handleLoad)
}
handleLoad() {
$("myclass") // $ is available here
}
}
在现代浏览器中,它应该是
try() {
if (!$("#element").size()) {
window.requestAnimationFrame(try);
} else {
// do your stuff
}
};
componentDidMount(){
this.try();
}
我发现,只需将
componentDidMount
或componentdiddupdate
中的代码包装为setTimeout
,时间为0毫秒,即可确保在执行setTimeout
功能之前,浏览器DOM已随React更改而更新
像这样:
componentDidMount() {
setTimeout(() => {
$("myclass") // $ is available here
}, 0)
}
这会将匿名函数放在JS事件队列中,以便在当前运行的React stack框架完成后立即运行。下面是我在尝试使用document.getElementsByClassName获取类之前,在DOM准备就绪时要等待的结果。我从componentDidMount()生命周期方法调用了这个函数
changeIcon() {
if (
document.getElementsByClassName('YOURCLASSNAME')
.length > 0 &&
document.getElementsByClassName('YOURCLASSNAME').length > 0
) {
document.getElementsByClassName(
'YOURCLASSNAME'
)[0].className = 'YOUR-NEW-CLASSNAME';
document.getElementsByClassName(
'YOUR-OTHER-EXISTING-CLASSNAME'
)[0].style.display = 'block';
} else {
setTimeout(this.changeIcon, 500);
}
}
组合使用
componentDidMount
和componentdiddupdate
将在带有类组件的代码中完成任务。
但是,如果您在用全部功能组件编写代码,那么效果挂钩将做得非常好,它与componentDidMount
和componentdiddupdate
是一样的
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
import React,{useState,useffect}来自“React”;
函数示例(){
const[count,setCount]=useState(0);
//与componentDidMount和componentDidUpdate类似:
useffect(()=>{
//使用浏览器API更新文档标题
document.title=`您单击了${count}次`;
});
返回(
您单击了{count}次
设置计数(计数+1)}>
点击我
);
}
您可以使用useRef
hook查看容器元素。
请注意,您需要特别注意ref
的当前值,否则它将无法工作
例如:
const containerRef = useRef();
const { current } = containerRef;
useEffect(setLinksData, [current]);
return (
<div ref={containerRef}>
// your child elements...
</div>
)
const containerRef=useRef();
const{current}=containerRef;
useffect(setLinksData,[当前]);
返回(
//您的子元素。。。
)
这对我来说似乎很有效
const [isLoaded, setIsLoaded] = useState(false);
const [isPageLoaded, setIsPageLoaded] = useState(false); //this helps
useEffect(() => {
setIsLoaded(true);
}, []);
useEffect(() => {
if (isLoaded) {
setIsPageLoaded(true);
}
}, [isLoaded]);
不幸的是,componentdiddupdate
没有为初始渲染调用,因此在道具或状态更改之前不会应用您的函数:呵呵,除了现代浏览器不使用jquery=P之外。不过这是使用动画帧的好技巧,假设它应该是实时更新的。但是componentDidUpdate将被多次调用,而实际上不是feasible@John什么方式不可行?@brianmearns在使用redux这样的状态管理库时,父道具可以多次更改,并且每次调用componentDidUpdate时都会更改。如果我们只需要等待初始DOM渲染,那么在这种情况下是不可行的。在这种情况下,在componentDidMount中附加负载侦听器似乎更好,如下面的一个答案所示。这是否只适用于顶级组件?此方法如何确保所有子组件都已完成渲染?当我使用此方法时,它为我提供了最大深度,因为它创建了一个无限循环。还记得添加remove eventlistenercomponentWillUnmount(){window.removeEventListener('load',this.handleLoad)}
我喜欢这个答案的方向,但是你的例子并不能解决这个问题。我认为这个问题与加载事件有关。使用useEffect钩子,您可以检测到用户访问“view/page/…”的时刻,而不是等待所有元素出现在屏幕中。设置超时的点是什么?我理解它在事件队列方面的作用,但为什么您认为这在这里是必要的?根据react文档,在加载/更新DOM元素之前,不会调用这两个方法。通过添加setTimeout,您在后续更新中引入了竞争条件。如果我在componentDidMount中直接调用我的lazyLoadImages函数,则位于浏览器选项卡中的页面加载指示器将一直旋转,直到加载所有图像。但如果wrap lazyLoadImages函数在setTimeout中使用100ms参数,这种情况就不同了。当图像开始在后台加载时,加载指示器将很快停止旋转。设置超时使体验更好。将延迟加载函数绑定到WindowOnLoad事件也会执行相同的操作,但它不适用于SPA。
const [isLoaded, setIsLoaded] = useState(false);
const [isPageLoaded, setIsPageLoaded] = useState(false); //this helps
useEffect(() => {
setIsLoaded(true);
}, []);
useEffect(() => {
if (isLoaded) {
setIsPageLoaded(true);
}
}, [isLoaded]);