单例ResizeObserver监听多个div时仅触发首个div回调的问题
问题分析与解决:ResizeObserver单例回调绑定错误
问题根源
你的核心问题是ResizeObserverUtility的单例逻辑仅在首次调用getInstance时保存了第一个DIV实例传入的回调,后续创建的DIV实例调用getInstance时,因为单例已存在,不会重新初始化ResizeObserver,导致所有resize事件触发时,始终执行第一个DIV的回调函数,this自然永远指向div-0。
修复方案:让单例支持多元素-回调映射
修改ResizeObserverUtility,通过Map存储每个监听元素对应的回调,确保每个元素的resize事件触发对应实例的逻辑:
class ResizeObserverUtility { static getInstance() { if (typeof ResizeObserver === 'undefined') { console.warn('ResizeObserver is not supported by this browser.'); return null; } if (!ResizeObserverUtility.instance) { console.log('Creating a new ResizeObserver instance'); // 用Map存储目标元素与对应回调的映射 const callbackMap = new Map(); ResizeObserverUtility.instance = new ResizeObserver(entries => { for (const entry of entries) { const { height, width } = entry.contentRect; // 根据当前触发resize的元素,取出对应的回调执行 const callback = callbackMap.get(entry.target); if (callback) { callback(height, width); } } }); // 扩展实例方法,用于注册元素和对应回调 ResizeObserverUtility.instance.observeWithCallback = function(target, callback) { callbackMap.set(target, callback); this.observe(target); }; // 可选:添加移除监听时清理回调的方法 ResizeObserverUtility.instance.unobserveWithCallback = function(target) { callbackMap.delete(target); this.unobserve(target); }; } return ResizeObserverUtility.instance; } }
然后修改DIV构造函数中的调用方式:
// 在DIV构造函数内 const util = ResizeObserverUtility.getInstance(); // 使用新增的observeWithCallback方法,传入当前元素和绑定好this的回调 util.observeWithCallback(this._domNode, (height, width) => this.exampleFunc(height, width));
方案优势
- 保留了应用级单例的性能优势,避免创建多个ResizeObserver实例
- 通过Map建立元素与回调的一一对应,确保每个元素的resize事件触发自身实例的逻辑
- 箭头函数保证了
exampleFunc中的this正确指向当前DIV实例
内容的提问来源于stack exchange,提问作者163lbs
相关产品推荐
相关产品推荐

