Javascript 在滚动时响应更改图像源事件
作为一个新加入React但熟悉JavaScript的人,我在知道在给定React组件中确切地放置某些功能时遇到了一些问题,并且不确定我遇到的这个问题是我的React逻辑问题还是加载图像时的延迟时间问题,虽然如果是后者,我不理解这一点,因为我将图像预加载到一个隐藏的div中 我的预期工作流程如下所示:Javascript 在滚动时响应更改图像源事件,javascript,css,reactjs,Javascript,Css,Reactjs,作为一个新加入React但熟悉JavaScript的人,我在知道在给定React组件中确切地放置某些功能时遇到了一些问题,并且不确定我遇到的这个问题是我的React逻辑问题还是加载图像时的延迟时间问题,虽然如果是后者,我不理解这一点,因为我将图像预加载到一个隐藏的div中 我的预期工作流程如下所示: componentDidMount() { if (this.props.changeColorOnScroll) { window.addEventListener("scro
componentDidMount() {
if (this.props.changeColorOnScroll) {
window.addEventListener("scroll", this.headerColorChange);
}
}
headerColorChange() {
console.log("Scroll Fire!");
const { classes, color, changeColorOnScroll} = this.props;
const windowsScrollTop = window.pageYOffset;
if (windowsScrollTop > changeColorOnScroll.height) {
document.body
.getElementsByTagName("header")[0]
.classList.remove(classes[color]);
document.body
.getElementsByTagName("header")[0]
.classList.add(classes[changeColorOnScroll.color]);
document
.getElementById("headerLogoContainer").getElementsByClassName("logo")[0]
.classList.add('hide');
document
.getElementById("headerLogoContainer").getElementsByClassName("logoalt")[0]
.classList.remove('hide');
} else {
document.body
.getElementsByTagName("header")[0]
.classList.add(classes[color]);
document.body
.getElementsByTagName("header")[0]
.classList.remove(classes[changeColorOnScroll.color]);
document
.getElementById("headerLogoContainer").getElementsByClassName("logo")[0]
.classList.remove('hide');
document
.getElementById("headerLogoContainer").getElementsByClassName("logoalt")[0]
.classList.add('hide');
}
}
hide
类的一部分隐藏
类,以便根据滚动位置有效地更改显示的图像。发生这种情况时,标题的背景色也将改变Header.jsx中,我有以下内容:
componentDidMount() {
if (this.props.changeColorOnScroll) {
window.addEventListener("scroll", this.headerColorChange);
}
}
headerColorChange() {
console.log("Scroll Fire!");
const { classes, color, changeColorOnScroll} = this.props;
const windowsScrollTop = window.pageYOffset;
if (windowsScrollTop > changeColorOnScroll.height) {
document.body
.getElementsByTagName("header")[0]
.classList.remove(classes[color]);
document.body
.getElementsByTagName("header")[0]
.classList.add(classes[changeColorOnScroll.color]);
document
.getElementById("headerLogoContainer").getElementsByClassName("logo")[0]
.classList.add('hide');
document
.getElementById("headerLogoContainer").getElementsByClassName("logoalt")[0]
.classList.remove('hide');
} else {
document.body
.getElementsByTagName("header")[0]
.classList.add(classes[color]);
document.body
.getElementsByTagName("header")[0]
.classList.remove(classes[changeColorOnScroll.color]);
document
.getElementById("headerLogoContainer").getElementsByClassName("logo")[0]
.classList.remove('hide');
document
.getElementById("headerLogoContainer").getElementsByClassName("logoalt")[0]
.classList.add('hide');
}
}
我相信这是在componentDidMount()
中附加事件侦听器的正确位置。我的问题是,当我滚动时,窗口会随着图像的更改而冻结,即使我在此处预加载了图像:
render() {
const {
classes,
color,
rightLinks,
leftLinks,
brand,
logo,
logoalt,
fixed,
absolute
} = this.props;
const appBarClasses = classNames({
[classes.appBar]: true,
[classes[color]]: color,
[classes.absolute]: absolute,
[classes.fixed]: fixed
});
let brandComponent;
if(!logo){
brandComponent = (
<Button className={classes.title}>
{brand}
</Button>
);
}else{
brandComponent = (
<div id='headerLogoContainer'>
<img className='logo' src={logo}></img>
<img className='logoalt hide' src={logoalt}></img>
</div>
);
}
return (
<AppBar className={appBarClasses}>
<Toolbar className={classes.container}>
{leftLinks !== undefined ? brandComponent : null}
<div className={classes.flex}>
{leftLinks !== undefined ? (
<Hidden smDown implementation="css">
{leftLinks}
</Hidden>
) : (
brandComponent
)}
</div>
然后在我的渲染中
render() {
const {
classes,
color,
rightLinks,
leftLinks,
brand,
logo,
logoalt,
fixed,
absolute
} = this.props;
const{
mobileOpen,
logoaltState
} = this.state
const appBarClasses = classNames({
[classes.appBar]: true,
[classes[color]]: color,
[classes.absolute]: absolute,
[classes.fixed]: fixed
});
let brandComponent;
if(!logo){
brandComponent = (
<Button className={classes.title}>
{brand}
</Button>
);
}else{
brandComponent = (
<div id='headerLogoContainer'>
<img className='logo' src={logo} style={{display: logoaltState === false ? "block" : "none"}}></img>
<img className='logoalt' src={logoalt} style={{display: logoaltState === true ? "block" : "none"}}></img>
</div>
);
}
render(){
常数{
班级,
颜色
右链接,
左链接,
品牌,
标志
logoalt,
固定的,
绝对的
}=这是道具;
常数{
移动电话,
logoaltState
}=这个州
const appBarClasses=类名({
[classes.appBar]:正确,
[类别[颜色]]:颜色,
[类别.绝对]:绝对,
[类别.固定]:固定
});
让brandComponent;
如果(!徽标){
品牌成分=(
{brand}
);
}否则{
品牌成分=(
);
}
不同的代码/方法,相同的问题
编辑2:
我不认为这是应用程序逻辑的问题,因为正如我所提到的,它只是在图像/状态第一次需要更改时冻结。我认为这是某种首次加载问题,即使我没有任何网络请求,可能我包括了错误的图像源?或者在React图像中需要预加载通过其他一些方法,因为图像源在包含时稍微关闭…即/static/media/logo.ad924167.png
而不是require(“assets/img/tovlogo.png”
我认为这是因为我的节点服务器设置,但我还是不太清楚到底发生了什么,因为我对这个生态系统相当陌生……我使用的是,这就是这个组件的来源
主题文件本身是这样的:所以我想知道它是如何处理图像的,考虑到实际的src
与require
的性质不同……但是,同样没有对图像的额外请求……这只是CSS/样式的改变
编辑3:
这就是我的调试器(Chrome:Performance)冻结时的样子:
我意识到在绘制时图像相当大,但不应该预加载地址…我想不是因为这是一个网络预加载,而不是带有display:none的绘制预加载;“
…也许我可以尝试使用不透明度
CSS属性,但这会使其他CSS复杂化…通常有更好的方法吗?”
最终编辑:
我的图像超过10000像素宽…我用它作为徽标,所以直到我做了性能指标后才意识到它有多糟糕…我猜这就是它冻结的原因…抱歉(与其手动更改DOM元素的类,不如利用组件状态,根据滚动位置在活动图像之间切换,这样会更容易
示例
类应用程序扩展了React.Component{
状态={active:0};
componentDidMount(){
window.addEventListener(“滚动”,this.handleScroll);
}
组件将卸载(){
window.removeEventListener(“滚动”,this.handleScroll);
}
handleScroll=事件=>{
常量{pageYOffset}=window;
const{active}=this.state;
如果(页面偏移量>=500&&active==0){
this.setState({active:1});
}else if(页面偏移<500&&active==1){
this.setState({active:0});
}
};
render(){
const{active}=this.state;
返回(
);
}
}
ReactDOM.render(,document.getElementById(“根”);
你能解释或链接到一个概念性的解释吗?这是简单的反应方式吗?我不明白为什么当事件侦听器中的if
条件启动时,直接访问DOM会失败。@SummerDeveloper是的,我没有比声明式呈现更好的解释了,也就是说,你应该尝试从状态和道具派生你的用户界面。当然,有一些方法是强制性的,但这是比较少见的。我不确定你问题中的代码为什么也不起作用。老实说,我不太明白。所以我是这样做的,反应方式,当图像发生变化时,我仍然会感到尴尬的延迟/冻结…有些时候还有其他事情在这里发生……有什么想法吗?因为我的图像是一幅巨大的图像,超过10000像素宽,我没有意识到……感谢关于州的指示,并对浪费的时间表示抱歉。:)