javascript - 如何在 ReactJS 的 onScroll 事件中操作 DOM?
问题描述
display: "none"
我正在尝试创建一个向上箭头按钮,如果我在页面顶部,它将设置为,当我进一步向下滚动时,我想将其设置为显示:“块”。我怎样才能做到这一点?我试图在我的 handleScroll 函数中操作 DOM,但它不起作用。
我的 TopButton.js 组件
import React from "react";
import "../assets/arrow-up.png";
class TopButton extends React.Component {
constructor(props) {
super(props);
this.handleScroll = this.handleScroll.bind(this);
}
componentDidMount = () => {
window.addEventListener("scroll", this.handleScroll, true);
};
handleClick = () => {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
};
handleScroll = () => {
console.log("scroll");
let x = document.getElementsByClassName("topbutton_button");
var x = document.getElementsByClassName("topbutton_button");
// x.style.display = "none";
// console.log(event.target.className);
// if (
// document.body.scrollTop > 40 ||
// document.documentElement.scrollTop > 40
// ) {
// style.display = "block";
// } else {
// display = "none";
// }
};
render() {
return (
<div className="topbutton_container">
<button
style={{ display: "block" }}
onClick={this.handleClick}
onScroll={this.handleScroll}
className="topbutton_button"
>
<img src={require("../assets/arrow-up.png")} />
</button>
</div>
);
}
}
export default TopButton;
解决方案
至少有两个原因它不起作用:
查看这个问题的答案;基本上,
getElementsByClassName
返回一个HTMLCollection
,而不是单个元素,但是您注释掉的代码将其视为单个元素。如果您的组件曾经被重新渲染,它将以其默认状态渲染,而不是您通过 DOM 更改的更新状态
但这不是你使用 React 的方式。相反,你会:
将按钮状态(无论它是否应该被阻止)在组件中保持为状态;
渲染时使用该状态
topbutton_button
,相应地设置其样式或类;和handleScroll
在您的处理程序中更新该状态
其他一些注意事项:
卸载组件时,您还需要删除处理程序
您不应该将箭头函数用于组件生命周期函数
您不需要
bind
在箭头函数上使用(handleScroll
例如)。要么使它成为箭头函数,要么在构造函数中使用bind
来绑定它。
这些方面的东西,请参阅***
评论
import React from "react";
import "../assets/arrow-up.png";
// *** Reusable function to decide whether we're "at the top" or not
function bodyIsAtTop() {
return (
document.body.scrollTop <= 40 &&
document.documentElement.scrollTop <= 40
);
}
class TopButton extends React.Component {
constructor(props) {
super(props);
// *** Initial state
this.state = {
atTop: bodyIsAtTop()
};
// *** No need for the following if you use an arrow function
// this.handleScroll = this.handleScroll.bind(this);
}
// *** Don't make this an arrow, make it a method
componentDidMount() {
window.addEventListener("scroll", this.handleScroll, true);
};
// *** Need to unbind when unmounted
componentWillUnmount = () => {
window.removeEventListener("scroll", this.handleScroll, true);
};
handleClick = () => {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
};
handleScroll = () => {
// *** Update state (possibly; if the flag isn't different, this doesn't do anything)
this.setState({atTop: bodyIsAtTop()});
};
render() {
// *** Get the flag from state, use it below in style
const {atTop} = this.state;
return (
<div className="topbutton_container">
<button
style={{ display: atTop ? "none" : "block" }}
onClick={this.handleClick}
onScroll={this.handleScroll}
className="topbutton_button"
>
<img src={require("../assets/arrow-up.png")} />
</button>
</div>
);
}
}
export default TopButton;
在那里,我将您的箭头功能保留为handleScroll
and handleClick
。有一个参数可以让它们成为方法并bind
在构造函数中使用,但这主要是一种风格。(嗯......风格,更容易模拟原型方法进行测试,这是使用原型方法和风格的非风格原因bind
。)
推荐阅读
- angular - Angular 5 - 如何为从数组列表创建的选择维护 ngmodel 数组
- c - UDP:每 x 秒从客户端读取一个新帧
- postgresql - JSQL Parser - 有关解析函数的信息
- c# - 如何在 .Net 1.1 中获取用户控件 HorizontalScroll 或 VerticalScroll 值
- php - 在 symfony2.8 中更新了用户和会话
- css - 如何在 Angular 2 / Ionic 2 中调整实时评论 div 的大小
- javascript - 如何通过ajax将数据数组发送到后端(php)
- android - 片段和列表视图子项
- javascript - 单个数组 [0] 项返回未定义
- ionic-framework - formbuilder 选择值作为对象