Vue3中如何监听this.$el.clientHeight实现Footer自适应置底?
针对你的需求,以下是无需依赖第三方库的原生监听方案,覆盖容器尺寸变化、图片加载完成、动态新增元素等场景,彻底替代定时器:
方案一:使用原生 ResizeObserver 监听容器高度(推荐)
利用浏览器原生的ResizeObserver API直接监听组件根元素的尺寸变化,无需额外安装依赖,同时结合图片加载监听处理海报加载后的高度更新:
export default { methods: { footerSticky() { const footerEl = this.$refs.footer; if (this.$el.clientHeight < window.innerHeight) { footerEl.classList.add('sticky-footer'); } else { footerEl.classList.remove('sticky-footer'); } }, initResizeObserver() { // 创建ResizeObserver实例 this.resizeObserver = new ResizeObserver(() => { this.footerSticky(); }); // 监听组件根元素 this.resizeObserver.observe(this.$el); } }, mounted() { // 初始化时先执行一次判断 this.footerSticky(); // 启动尺寸监听 this.initResizeObserver(); // 处理页面内图片加载完成后的高度变化 document.querySelectorAll('img').forEach(img => { if (img.complete) { this.footerSticky(); } else { img.addEventListener('load', () => this.footerSticky()); } }); }, beforeUnmount() { // 组件销毁前断开监听,避免内存泄漏 if (this.resizeObserver) { this.resizeObserver.unobserve(this.$el); this.resizeObserver.disconnect(); } } }
方案二:结合 window.resize + MutationObserver 兼容更复杂场景
如果需要兼容极旧浏览器(现代浏览器已普遍支持ResizeObserver),或者要监听动态新增元素的情况,可以使用此方案,同时加入防抖优化减少性能消耗:
export default { data() { return { resizeTimeout: null, mutationObserver: null } }, methods: { footerSticky() { const footerEl = this.$refs.footer; if (this.$el.clientHeight < window.innerHeight) { footerEl.classList.add('sticky-footer'); } else { footerEl.classList.remove('sticky-footer'); } }, handleResize() { // 防抖:300ms内仅执行一次判断,避免频繁触发 clearTimeout(this.resizeTimeout); this.resizeTimeout = setTimeout(() => { this.footerSticky(); }, 300); } }, mounted() { this.footerSticky(); // 监听窗口尺寸变化 window.addEventListener('resize', this.handleResize); // 监听图片加载 document.querySelectorAll('img').forEach(img => { if (img.complete) { this.footerSticky(); } else { img.addEventListener('load', () => this.footerSticky()); } }); // 监听组件内DOM变化,应对未来新增元素的情况 this.mutationObserver = new MutationObserver(() => { this.footerSticky(); // 对新增元素中的图片补充加载监听 document.querySelectorAll('img').forEach(img => { img.addEventListener('load', () => this.footerSticky()); }); }); this.mutationObserver.observe(this.$el, { childList: true, subtree: true }); }, beforeUnmount() { // 清理监听和定时器 window.removeEventListener('resize', this.handleResize); clearTimeout(this.resizeTimeout); if (this.mutationObserver) { this.mutationObserver.disconnect(); } } }
配套CSS样式
确保sticky-footer类的样式能正确固定底部:
.sticky-footer { position: fixed; bottom: 0; left: 0; right: 0; background-color: #ffffff; /* 与页面背景色保持一致,避免被内容穿透 */ z-index: 10; /* 按需设置层级,防止被其他元素遮挡 */ }
内容的提问来源于stack exchange,提问作者Twilight
相关产品推荐
相关产品推荐

