我在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。然而,这使得滚动无法使用,因为它非常慢。
有什么建议吗?
我通过使用和修改CSS变量解决了这个问题。这样我就不必修改会导致性能问题的组件状态。
index.css
:root {
--navbar-background-color: rgba(95,108,255,1);
}
Navbar.jsx
import React, { Component } from 'react';
import styles from './Navbar.module.css';
class Navbar extends Component {
documentStyle = document.documentElement.style;
initalNavbarBackgroundColor = 'rgba(95, 108, 255, 1)';
scrolledNavbarBackgroundColor = 'rgba(95, 108, 255, .7)';
handleScroll = () => {
if (window.scrollY === 0) {
this.documentStyle.setProperty('--navbar-background-color', this.initalNavbarBackgroundColor);
} else {
this.documentStyle.setProperty('--navbar-background-color', this.scrolledNavbarBackgroundColor);
}
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
render () {
return (
<nav className={styles.Navbar}>
<a href="/">Home</a>
<a href="#about">About</a>
</nav>
);
}
};
export default Navbar;
Navbar.module.css
.Navbar {
background: var(--navbar-background-color);
}
您应该在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
});
},
我的解决方案,使一个响应式导航栏(位置:“相对”时不滚动和固定时滚动,而不是在页面顶部)
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
handleScroll(event) {
if (window.scrollY === 0 && this.state.scrolling === true) {
this.setState({scrolling: false});
}
else if (window.scrollY !== 0 && this.state.scrolling !== true) {
this.setState({scrolling: true});
}
}
<Navbar
style={{color: '#06DCD6', borderWidth: 0, position: this.state.scrolling ? 'fixed' : 'relative', top: 0, width: '100vw', zIndex: 1}}
>
对我来说没有性能问题。
我通过使用和修改CSS变量解决了这个问题。这样我就不必修改会导致性能问题的组件状态。
index.css
:root {
--navbar-background-color: rgba(95,108,255,1);
}
Navbar.jsx
import React, { Component } from 'react';
import styles from './Navbar.module.css';
class Navbar extends Component {
documentStyle = document.documentElement.style;
initalNavbarBackgroundColor = 'rgba(95, 108, 255, 1)';
scrolledNavbarBackgroundColor = 'rgba(95, 108, 255, .7)';
handleScroll = () => {
if (window.scrollY === 0) {
this.documentStyle.setProperty('--navbar-background-color', this.initalNavbarBackgroundColor);
} else {
this.documentStyle.setProperty('--navbar-background-color', this.scrolledNavbarBackgroundColor);
}
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
render () {
return (
<nav className={styles.Navbar}>
<a href="/">Home</a>
<a href="#about">About</a>
</nav>
);
}
};
export default Navbar;
Navbar.module.css
.Navbar {
background: var(--navbar-background-color);
}
一个使用classNames, React挂钩useEffect, useState和styles -jsx的例子:
import classNames from 'classnames'
import { useEffect, useState } from 'react'
const Header = _ => {
const [ scrolled, setScrolled ] = useState()
const classes = classNames('header', {
scrolled: scrolled,
})
useEffect(_ => {
const handleScroll = _ => {
if (window.pageYOffset > 1) {
setScrolled(true)
} else {
setScrolled(false)
}
}
window.addEventListener('scroll', handleScroll)
return _ => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
return (
<header className={classes}>
<h1>Your website</h1>
<style jsx>{`
.header {
transition: background-color .2s;
}
.header.scrolled {
background-color: rgba(0, 0, 0, .1);
}
`}</style>
</header>
)
}
export default Header