我在React中构建了一个组件,它应该在窗口滚动上更新自己的风格,以创建视差效果。
组件渲染方法是这样的:
function() {
let style = { transform: 'translateY(0px)' };
window.addEventListener('scroll', (event) => {
let scrollTop = event.srcElement.body.scrollTop,
itemTranslate = Math.min(0, scrollTop/3 - 60);
style.transform = 'translateY(' + itemTranslate + 'px)');
});
return (
<div style={style}></div>
);
}
这是行不通的,因为React不知道组件已经更改,因此组件不会重新呈现。
我已经尝试在组件的状态中存储itemTranslate的值,并在滚动回调中调用setState。然而,这使得滚动无法使用,因为它非常慢。
有什么建议吗?
用钩子:
import React, { useEffect, useState } from 'react';
function MyApp () {
const [offset, setOffset] = useState(0);
useEffect(() => {
const onScroll = () => setOffset(window.pageYOffset);
// clean up code
window.removeEventListener('scroll', onScroll);
window.addEventListener('scroll', onScroll, { passive: true });
return () => window.removeEventListener('scroll', onScroll);
}, []);
console.log(offset);
};
使用useEffect的函数组件示例:
注意:你需要通过在useEffect中返回一个“清理”函数来删除事件监听器。如果不这样做,每次组件更新时,都会有一个额外的窗口滚动侦听器。
import React, { useState, useEffect } from "react"
const ScrollingElement = () => {
const [scrollY, setScrollY] = useState(0);
function logit() {
setScrollY(window.pageYOffset);
}
useEffect(() => {
function watchScroll() {
window.addEventListener("scroll", logit);
}
watchScroll();
// Remove listener (like componentWillUnmount)
return () => {
window.removeEventListener("scroll", logit);
};
}, []);
return (
<div className="App">
<div className="fixed-center">Scroll position: {scrollY}px</div>
</div>
);
}
您应该在componentDidMount中绑定侦听器,这样它只创建一次。您应该能够在状态中存储样式,侦听器可能是性能问题的原因。
就像这样:
componentDidMount: function() {
window.addEventListener('scroll', this.handleScroll);
},
componentWillUnmount: function() {
window.removeEventListener('scroll', this.handleScroll);
},
handleScroll: function(event) {
let scrollTop = event.srcElement.body.scrollTop,
itemTranslate = Math.min(0, scrollTop/3 - 60);
this.setState({
transform: itemTranslate
});
},
用钩子:
import React, { useEffect, useState } from 'react';
function MyApp () {
const [offset, setOffset] = useState(0);
useEffect(() => {
const onScroll = () => setOffset(window.pageYOffset);
// clean up code
window.removeEventListener('scroll', onScroll);
window.addEventListener('scroll', onScroll, { passive: true });
return () => window.removeEventListener('scroll', onScroll);
}, []);
console.log(offset);
};