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

Bor*_*rsn 4 javascript addeventlistener reactjs styled-components

在调整大小时,甚至不会触发侦听器。

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>
      );
  }

}
Run Code Online (Sandbox Code Playgroud)

--

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;
`;
Run Code Online (Sandbox Code Playgroud)

我在这里做错了什么?

我试图检测div又名Container元素何时styled-components改变大小。

3li*_*t0r 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"));
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

可能还有一些库可以帮助您组合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 />);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)