即使监听器未触发也会调整大小

问题描述 投票:0回答:2

调整大小时,即使侦听器也不会被触发。

class MainContainer extends React.Component {
  constructor(props) {
    super(props);
    this.containerRef = React.createRef();
    this.state = {};
  }

  componentDidMount() {
    this.containerRef.current.addEventListener("resize", this.handleResize);
  }

  componentWillUnmount() {
    this.containerRef.current.removeEventListener("resize", this.handleResize);
  }

  handleResize() {
    console.log("handleResize");
  }

  render() {
      return (
        <React.Fragment>
          <Container ref={this.containerRef}>
            <Body />
          </Container>
          <ShadowTop show={this.state.top} />
        </React.Fragment>
      );
  }

}

--

export const Container = styled.div`
  @media (max-width: 760px) {
    position: absolute;
  }

  margin-top: ${({ theme }) => theme.header.height.percent}%;
  margin-top: -webkit-calc(${({ theme }) => theme.header.height.pixel}px);
  margin-top: -moz-calc(${({ theme }) => theme.header.height.pixel}px);
  margin-top: calc(${({ theme }) => theme.header.height.pixel}px);

  height: ${({ theme }) => Math.abs(100 - theme.header.height.percent)}%;
  height: -webkit-calc(100% - ${({ theme }) => theme.header.height.pixel}px);
  height: -moz-calc(100% - ${({ theme }) => theme.header.height.pixel}px);
  height: calc(100% - ${({ theme }) => theme.header.height.pixel}px);

  position: fixed;
  float: none;
  clear: both;
  top: 0;
  right: 0;

  width: ${({ theme }) => 100 - theme.sidebar.width.percent}%;
  width: -webkit-calc(100% - ${({ theme }) => theme.sidebar.width.pixel}px);
  width: -moz-calc(100% - ${({ theme }) => theme.sidebar.width.pixel}px);
  width: calc(100% - ${({ theme }) => theme.sidebar.width.pixel}px);


  z-index: 2;
  pointer-events: auto;
  overflow: auto;
`;

我在这里做错了什么?

我正在尝试检测

div
又名
Container
styled-components
元素何时更改了大小。

javascript reactjs styled-components addeventlistener
2个回答
6
投票

resize
事件在
window
上触发,而不是在单个元素上触发。这是因为
resize
事件旨在处理视口调整大小,而不是内容调整大小。要检测内容大小变化,您可以使用
ResizeObserver

您可以通过多种方式将其合并到您的 React 项目中。这是一个与您的问题类似的示例:

class MainContainer extends React.Component {
  constructor(props) {
    super(props);
    
    this.ulRef = React.createRef();
    this.state = { todoList: [] };
    
    // Binding methods to the current intance is only needed if you pass
    // the method as an argument to another function and want acces to the
    // `this` keyword in the method.
    this.handleResize = this.handleResize.bind(this);
    this.addTodoItem = this.addTodoItem.bind(this);
  }

  componentDidMount() {
    this.ulObserver = new ResizeObserver(this.handleResize);
    this.ulObserver.observe(this.ulRef.current);
  }

  componentWillUnmount() {
    this.ulObserver.disconnect();
  }

  handleResize(entries, observer) {
    console.log("handleResize", entries);
    // ...
  }
  
  addTodoItem(event) {
    event.preventDefault();
    const formData = new FormData(event.target);
    this.setState((state) => ({
      todoList: [...state.todoList, formData.get("todo-item")],
    }));
  }

  render() {  
    return (
      <div>
        <form onSubmit={this.addTodoItem}>
          <input name="todo-item" />
          <button>add</button>
          {" "}(or press <kbd>Enter</kbd>)
        </form>
        <ul ref={this.ulRef}>
          {this.state.todoList.map((item, index) => (
            <li key={index}>{item}</li>
          ))}
        </ul>
      </div>
    );
  }
}

ReactDOM.render(<MainContainer />, document.querySelector("#root"));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

可能还有一些库可以帮助您将

ResizeObserver
和 React 结合起来。但了解幕后发生的事情并没有什么坏处。


对于那些寻找更现代的功能组件解决方案的人:

const { createRef, useState, useCallback, useEffect } = React;

function MainContainer() {
  const ulRef = createRef();
  const [todoList, setTodoList] = useState([]);
  
  const addTodoItem = useCallback(function (event) {
    event.preventDefault();
    const formData = new FormData(event.target);
    setTodoList(todoList => [...todoList, formData.get("todo-item")]);
  }, []);
  
  const handleResize = useCallback(function (entries, observer) {
    console.log("handleResize", entries);
    // ...
  }, []);
  
  useEffect(function () {
    const ulObserver = new ResizeObserver(handleResize);
    ulObserver.observe(ulRef.current);
    return () => ulObserver.disconnect();
  }, [handleResize]);
  
  return (
    <div>
      <form onSubmit={addTodoItem}>
        <input name="todo-item" />
        <button>add</button>
        {" "}(or press <kbd>Enter</kbd>)
      </form>
      <ul ref={ulRef}>
        {todoList.map((item, index) => <li key={index}>{item}</li>)}
      </ul>
    </div>
  );
}

ReactDOM.createRoot(document.querySelector("#root")).render(<MainContainer />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>


0
投票

调整大小事件仅在窗口对象上触发

您可以阅读有关调整大小事件

的更多信息

应该是:

componentDidMount() {
  window.addEventListener('resize', this.handleResize);
}
componentWillUnmount() {
  window.removeEventListener('resize', this.handleResize);
}

您可以将

debounce
添加到 handleResize 以减少使用频率。

© www.soinside.com 2019 - 2024. All rights reserved.