报错的原因:在页面绘制的时候,页面突然发生调整大小的事件,导致了样式和布局都需要重新评估,这个调整大小导致的布局变化,将延迟到下一帧来绘制。
方法1:
这时我们将下面的代码放入app.vue的<script>中就能解决以上问题。
// 解决ERROR ResizeObserver loop completed with undelivered notifications.
// 重写ResizeObserver的构造函数,并在其中定义并调用防抖函数
window.ResizeObserver = class ResizeObserver extends window.ResizeObserver {
constructor(callback) {
let timer = null;
const debouncedCallback = function () {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
callback.apply(context, args);
}, 16);
};
super(debouncedCallback);
}
};
下面是对这个代码的解释:
首先,debounce
函数用于限制一个函数的执行频率,确保在一定时间间隔内只执行一次。它接受两个参数,一个是要执行的函数fn
,另一个是延迟时间delay
。函数内部使用setTimeout
来实现延迟执行,每次调用时会清除之前的定时器,然后设置一个新的定时器来延迟执行目标函数。
接下来,代码对window.ResizeObserver
进行了扩展。它将原始的ResizeObserver
保存为_ResizeObserver
,然后定义了一个新的ResizeObserver
类,重写了其构造函数。在新的构造函数中,传入的回调函数被用debounce
函数处理,确保回调函数在16毫秒的间隔内执行一次。这样做是为了限制ResizeObserver
的回调频率,以避免过多的触发,提高性能。
这段代码实现了对ResizeObserver
的改写,通过限制回调函数的执行频率来优化性能。
通过调整回调频率能解决上面讲解的问题报错原因。
方法2:
window.ResizeObserver = class ResizeObserver extends _ResizeObserver {
constructor(callback) {
super(entries => {
// 使用requestAnimationFrame来延迟执行回调函数
requestAnimationFrame(() => {
callback(entries);
});
});
}
}
利用了requestAnimationFrame的特性,它会在浏览器完成下一次渲染之前执行回调函数,因此可以避免在渲染过程中触发新的测量。这样就不需要手动实现防抖函数,而是利用浏览器提供的API来处理ResizeObserver的回调。