调整大小时,即使侦听器也不会被触发。
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
元素何时更改了大小。
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>
调整大小事件仅在窗口对象上触发
您可以阅读有关调整大小事件
的更多信息应该是:
componentDidMount() {
window.addEventListener('resize', this.handleResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
}
您可以将
debounce
添加到 handleResize 以减少使用频率。