javascript - 如何正确更新 React 中的类名?
问题描述
在向下滚动时,我添加和删除了某些类。我想在向上滚动时恢复课程。如何仅使用 ReactJS 来完成?
我已经使用事件侦听器来更改类。
主要概念是导航栏的内容应该显示在中心,当我们向下滚动时,显示在一个div中的网站名称应该显示在导航栏上,而放在中间的内容应该向左移动显示网站名称的 div 应该会消失。当我们向上滚动到带有网站名称的 div 时,一切都应该恢复到向下滚动之前的状态。
import React, { Component } from 'react';
import '../Styles/Navbar.css';
export class Navbar extends Component {
handleScrollToElement(event) {
let linkPosition = document.querySelector('.collapse');
let brandName = document.querySelector('.navbar-brand');
if (window.pageYOffset > 250){
linkPosition.classList.remove('justify-content-center');
linkPosition.classList.add('justify-content-end');
brandName.classList.remove('invisible');
brandName.classList.add('visible');
}
}
componentDidMount() {
window.addEventListener('scroll', this.handleScrollToElement);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScrollToElement);
}
render() {
return (
<div>
<nav className='navbar navbar-expand-sm bg-dark navbar-dark fixed-top'>
<a className='navbar-brand invisible' href='#'>Website Name</a>
<button className='navbar-toggler' type='button' data-toggle='collapse' data-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
<span className='navbar-toggler-icon'></span>
</button>
<div className='collapse navbar-collapse justify-content-center' id='navbarSupportedContent'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<a className='nav-link' href='#'>Home</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Item 2</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>About Us</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Contact</a>
</li>
</ul>
</div>
</nav>
<div className='container-fluid hpage'>
<div className='inner'>
<h1 className='htext' >WEBSITE TITLE</h1>
</div>
</div>
</div>
)
}
}
export default Navbar;
解决方案
当你使用 React.js 时,你应该尽可能避免直接的 DOM 操作。如果你真的需要一个 DOM 的引用,你应该使用ref来代替。
我将设置classNames
为linkPosition
和brandName
作为状态constructor
并更新它们handleScrollToElement
。
每当state
更改这些变量时,render
都会调用该函数并更新视图。
由于scroll
事件在短时间内触发很多,我也担心性能问题。所以我在代码中添加了shouldComponentUpdate以防止重新渲染未更改的视图。
您还可以考虑对要调用的滚动事件处理函数进行去抖动处理,以减少调用setState
.
import React, { Component } from 'react';
import '../Styles/Navbar.css';
export class Navbar extends Component {
constructor(props) {
super(props);
this.state = {
linkPositionClassName: 'justify-content-center',
brandNameClassName: 'invisible',
};
}
handleScrollToElement(event) {
if (window.pageYOffset > 250){
this.setState({
linkPositionClassName: 'justify-content-end',
brandNameClassName: 'visible',
});
} else {
this.setState({
linkPositionClassName: 'justify-content-center',
brandNameClassName: 'invisible',
});
}
}
shouldComponentUpdate(nextProps, nextState) {
const { linkPositionClassName, brandNameClassName } = this.state;
// component needs to re-render only when at least one of the state changes
return nextState.linkPositionClassName !== linkPositionClassName || nextState.brandNameClassName !== brandNameClassName;
}
componentDidMount() {
window.addEventListener('scroll', this.handleScrollToElement);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScrollToElement);
}
render() {
return (
<div>
<nav className='navbar navbar-expand-sm bg-dark navbar-dark fixed-top'>
<a className=`navbar-brand ${this.state.brandNameClassName}` href='#'>Website Name</a>
<button className='navbar-toggler' type='button' data-toggle='collapse' data-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
<span className='navbar-toggler-icon'></span>
</button>
<div className=`collapse navbar-collapse ${this.state.linkPositionClassName}` id='navbarSupportedContent'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<a className='nav-link' href='#'>Home</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Item 2</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>About Us</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Contact</a>
</li>
</ul>
</div>
</nav>
<div className='container-fluid hpage'>
<div className='inner'>
<h1 className='htext' >WEBSITE TITLE</h1>
</div>
</div>
</div>
)
}
}
export default Navbar;
推荐阅读
- ssh - 在 git bash 中生成 SSH 密钥,我无法获取 git 代理
- dart - 接受对象作为函数
- intellij-idea - Intellij IDEA - 多次打印事件日志
- javascript - Firebase - 在验证电子邮件之前冻结帐户
- javascript - 如何将用户凭据发布到外部域?
- html - SQLSTATE [42S22]:找不到列:1054 'where 子句'中的未知列'user_id'
- java - Spring Tomcat JDBC 连接池 - 如何在数据库脱机时恢复
- reactjs - create-react-app 占用过多磁盘空间和时间
- ruby - 收集和比较数组内的 ruby 哈希
- javascript - 三个(几乎?)相同的函数返回不同的结果