触发'调整大小'组件上的事件?

时间:2016-06-12 13:51:11

标签: javascript reactjs

我正在编写一个组件装饰器,它能够检测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可用?

注意:我不想要一种方法来检测组件的大小调整,我只需要向React发送一个事件并使其onResize

可以访问它

2 个答案:

答案 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" />