js 使用 ResizeObserver 时报错,代码实现逻辑如下:
function observeVideoDom (width: number, height: number) {
const videoDom = document.getElementById('videoDom')
if (!videoDom) return
if (window.ResizeObserver) {
// ResizeObserver 在 iOS13.4及以上,安卓 4.4.5及以上才支持,如果不支持用轮询判断
const resizeObserver = new ResizeObserver(() => {
videoSizeReset(width, height)
})
resizeObserver.observe(videoDom)
} else {
let previousWidth = videoDom.clientWidth
let previousHeight = videoDom.clientHeight
const checkSize = () => {
const currentWidth = videoDom.clientWidth
const currentHeight = videoDom.clientHeight
if (currentWidth !== previousWidth || currentHeight !== previousHeight) {
videoSizeReset(width, height)
previousWidth = currentWidth
previousHeight = currentHeight
}
}
const scheduleCheck = () => {
checkSize()
requestAnimationFrame(scheduleCheck)
}
requestAnimationFrame(scheduleCheck)
}
}
主要功能是监测 videoDom 元素的盒子大小变化后,重新赋值videoDom 元素的盒子大小,由于重新赋值的操作会再次改变 videoDom 元素的盒子大小,会导致报错了 ResizeObserver loop completed with undelivered notifications.
解决方案,给 ResizeObserver 的回调函数加 防抖或者 requestAnimationFrame
改后如下:
function observeVideoNativeDom (width: number, height: number) {
const videoNativeDom = document.getElementById('video-native')
if (!videoNativeDom) return
if (window.ResizeObserver) {
// ResizeObserver 在 iOS13.4及以上,安卓 4.4.5及以上才支持,如果不支持用轮询判断
const resizeObserver = new ResizeObserver(debounce(() => {
videoSizeReset(width, height)
}, 300))
resizeObserver.observe(videoNativeDom)
} else {
let previousWidth = videoNativeDom.clientWidth
let previousHeight = videoNativeDom.clientHeight
const checkSize = () => {
const currentWidth = videoNativeDom.clientWidth
const currentHeight = videoNativeDom.clientHeight
if (currentWidth !== previousWidth || currentHeight !== previousHeight) {
videoSizeReset(width, height)
previousWidth = currentWidth
previousHeight = currentHeight
}
}
const scheduleCheck = () => {
checkSize()
requestAnimationFrame(scheduleCheck)
}
requestAnimationFrame(scheduleCheck)
}
}
// 或者
debounce 函数自己写或者引入工具库