簡體   English   中英

我如何在 ReactJS 的 onScroll 事件中操作 DOM?

[英]How can i manipulate DOM inside the onScroll event in ReactJS?

我正在嘗試創建一個向上箭頭按鈕,如果我在頁面頂部,它將設置為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 做的事情。 相反,你會:

  1. 將按鈕狀態(無論是否應為塊狀態)作為組件中的狀態保存;

  2. 在渲染topbutton_button時使用該狀態,相應地設置其樣式或類;

  3. handleScroll處理程序中更新該狀態

其他一些注意事項:

  • 您還需要在卸載組件時刪除處理程序

  • 您不應該將箭頭函數用於組件生命周期函數

  • 您不需要在箭頭函數(例如handleScroll )上使用bind 要么使它成為箭頭函數,要么在構造函數中使用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;

我在那里保留了handleScrollhandleClick的箭頭功能。 有一種說法是讓它們成為方法並在構造函數中使用bind ,但這主要是一種風格。 (好吧......樣式並且模擬原型方法進行測試更容易,這是使用原型方法和bind的非樣式原因。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM