前言
有时候我们需要监听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来进行。