监听dom大小改变的实现

97 阅读1分钟

在项目中,总是需要展示数据,会用到一些表格,同时也会用到一些自适应宽度的布局,可能会遇到页面区域是动态的时候图表的一个自适应。一般的自适应是适应不同屏幕尺寸或窗口大小的改变,不需要考虑元素容器大小的改变。

/* 
* 描述:监听dom大小的变化  
* new 实例时传入一个需要监听的dom和响应函数,(oldSize,nowSize)=>{}
* instance.bind(el,()=>{})添加更多元素,instance.remove(el)移除监听
*/
class DomSizeListener {
  constructor(el, next) {
    this.timer = null;
    this.elList = [];
    this.el = el;
    this.next = next;

    this.init();
  }
  init() {
    this.bind(this.el, this.next)
    this.timer = setInterval(() => {
      for (let i = 0; i < this.elList.length; i++) {
        let dom = this.elList[i].el
        const style = {
          width: this._getStyle(dom, 'width'),
          height: this._getStyle(dom, 'height'),
        }
        if (!this._isEqul(style, this.elList[i].style)) {
          let oldStyle = this.elList[i].style;
          this.elList[i].style = {
            width: style.width,
            height: style.height,
          }
          let newStyle = this.elList[i].style;
          this.elList[i].callback && this.elList[i].callback(oldStyle, newStyle);
        }
      }
    }, 200)
  }
  bind(el, next) {
    let obj = {
      el,
      callback: next,
      style: {
        width: this._getStyle(el, 'width'),
        height: this._getStyle(el, 'height'),
      }
    }
    this.elList.push(obj);
  }
  remove(el) {
    this.elList.splice(this.elList.indexOf(el))
    if (this.elList.indexOf(el) !== -1) {
      this.elList.splice(this.elList.indexOf(el), 1);
    }
  }

  _getStyle(ele, attr) {
    if (window.getComputedStyle) {
      return window.getComputedStyle(ele, null)[attr];
    }
    return ele.currentStyle[attr];
  }
  _isEqul(obj1, obj2) {
    let isEqul = true;
    for (var i in obj1) {
      if (obj1[i] !== obj2[i]) {
        isEqul = false;
      }
    }
    return isEqul;
  }
}

最后,这只是根据需要实现的一种方法,另外可以使用浏览器提供的api--ResizeObserver.