3

JS监听dom高度变化方法总结

 1 year ago
source link: https://www.haorooms.com/post/js_dom_height
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

有时候我们需要监听dom的变化,例如有时候图片未加载完就取 dom 的高度,这样会导致高度不正确,所以需要监听 dom 的高度变化。才能准确获取dom的高度,那么有哪些监听dom高度变化的方法呢?今天简单列举一下。

监听dom树变化DOMNodeInserted

可以用DOMNodeInserted事件监听子元素是否改变,但是不是很准确。

var dom = document.getElementById('dom');
var height = dom.offsetHeight;
dom.addEventListener('DOMNodeInserted', function () {
  var newHeight = dom.offsetHeight;
  if (newHeight !== height) {
    console.log('dom高度变化了');
    height = newHeight;
  }
});

MutationObserver 构造函数

Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。 目前来看,IE11及以上都可以兼容。兼容性还可以,可以大胆使用。

MutationObserver 构造函数的实例传的是一个回调函数,该函数接受两个参数,第一个是变动的数组,第二个是观察器的实例。

var observer = new MutationObserver(function (mutations, observer){
  mutations.forEach(function (mutaion) {
    console.log(mutation);
  })
})

MutationObserver 的应用

var haoroomsId = document.getElementById('haorooms');
var MutationObserver = window.MutationObserver || window.webkitMutationObserver || window.MozMutationObserver;

var recordHeight = 0;
var mutationObserver = new MutationObserver(function (mutations) {
  console.log(mutations);

  let height = window.getComputedStyle(haoroomsId).getPropertyValue('height');
  if (height === recordHeight) {
    return;
  }
  recordHeight = height;
  console.log('高度变化了');
  // 之后更新外部容器等操作
})

mutationObserver.observe(haoroomsId, {
  childList: true, // 子节点的变动(新增、删除或者更改)
  attributes: true, // 属性的变动
  characterData: true, // 节点内容或节点文本的变动
  subtree: true // 是否将观察器应用于该节点的所有后代节点
})

针对动画animation、transform监听不到的情况,可以在动画完成监听高度就可以了

  el.addEventListener('animationend', onHeightChange)

    el.addEventListener('transitionend', onHeightChange)

ResizeObserver

ResizeObserver 是新的API,处于实验阶段,因此,兼容性不太好,文档:https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver

使用很简单

// create an Observer instance
const resizeObserver = new ResizeObserver((entries) =>
  console.log('Body height changed:', entries[0].target.clientHeight)
);

// start observing a DOM node
resizeObserver.observe(document.body);

ResizeObserver Polyfill

实验性的 API 不足,可以用 Polyfill 来弥补

ResizeObserver Polyfill 利用事件冒泡,在顶层 document 上监听动画 transitionend;

监听 window 的 resize 事件;

其次用 MutationObserver 监听 document 元素;

兼容IE11以下 通过 DOMSubtreeModified 监听 document 元素。

/**
 * Initializes DOM listeners.
 *
 * @private
 * @returns {void}
 */
ResizeObserverController.prototype.connect_ = function () {
    // Do nothing if running in a non-browser environment or if listeners
    // have been already added.
    if (!isBrowser || this.connected_) {
        return;
    }
    // Subscription to the "Transitionend" event is used as a workaround for
    // delayed transitions. This way it's possible to capture at least the
    // final state of an element.
    document.addEventListener('transitionend', this.onTransitionEnd_);
    window.addEventListener('resize', this.refresh);
    if (mutationObserverSupported) {
        this.mutationsObserver_ = new MutationObserver(this.refresh);
        this.mutationsObserver_.observe(document, {
            attributes: true,
            childList: true,
            characterData: true,
            subtree: true
        });
    }
    else {
        document.addEventListener('DOMSubtreeModified', this.refresh);
        this.mutationEventsAdded_ = true;
    }
    this.connected_ = true;
};

以上就是总结的js如何监听dom变化的方法,假如你不用兼容老的浏览器,可以用最新的ResizeObserver,当然也可以用ResizeObserver,配合Polyfill来进行。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK