我正在编写一个组件装饰器,它能够检测DOM元素的大小何时被改变(通过css,javascript,window resize等)。
它已经完美运行了,我现在正试图让它的API易于使用,那么,比这更容易吗?
class Foobar extends React.Component {
render() {
return <div onResize={() => console.log('resized!')}>Foobar</div>;
}
}
ReactDOM.render(resizeAware(Foobar), app);
我遇到的问题是,当我触发它时,onResize
事件没有被触发......
这是两次触发事件的尝试:
// method 1
onResize() {
const resizeEvent = document.createEvent('HTMLEvents');
resizeEvent.initEvent('resize', true, true);
console.log('triggering resize...');
findDOMNode(this.componentNode).dispatchEvent(resizeEvent);
}
// method 2
onResize() {
console.log('triggering resize...');
findDOMNode(this.componentNode).dispatchEvent(new Event('resize'));
}
如果我用以下方式收听活动:
findDOMNode(this).addEventListener('resize', () => console.log('resized'));
一切正常。所以看起来我调度的事件是由真正的DOM元素而不是虚拟DOM接收的。
现在的问题是,为什么没有调用onResize
回调?
如果没有解决方案,您将如何使我的装饰器API可用?
onResize
答案 0 :(得分:1)
Another NPM lib收听div的resize事件。查看demo
答案 1 :(得分:-1)
我使用了post并将其简单地转换为React组件。您需要做的就是在componentDidMount中定义一个MutationObserver,以便它可以监视调整大小
class ResizableDiv extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
componentDidMount() {
const element = this.ref.current;
element.addEventListener('resize', (event) => console.log(event.detail));
function checkResize(mutations) {
const el = mutations[0].target;
const w = el.clientWidth;
const h = el.clientHeight;
const isChange = mutations
.map((m) => `${m.oldValue}`)
.some((prev) => prev.indexOf(`width: ${w}px`) === -1 || prev.indexOf(`height: ${h}px`) === -1);
if (!isChange) { return; }
const event = new CustomEvent('resize', { detail: { width: w, height: h } });
el.dispatchEvent(event);
}
const observer = new MutationObserver(checkResize);
observer.observe(element, { attributes: true, attributeOldValue: true, attributeFilter: ['style'] });
}
render() {
return ( <div ref={this.ref} className='drag'> Resize me! < /div>);
}
}
ReactDOM.render( < ResizableDiv / > ,
document.getElementById('root')
);
.drag {
border: 1px solid red;
width: 200px;
height: 100px;
resize: both;
overflow: hidden;
}
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<div id="root" />