Uni-app H5 环境下 ResizeObserver 监听 mp-html 动态高度

在 Uni-app 混合开发中,处理 H5 WebView 环境下富文本内容的动态高度是一个常见难题。本文聚焦于 mp-html 组件的特定场景,分析 ResizeObserver 的应用价值与潜在风险。

1. 业务背景:mp-html 渲染的遮罩层动态适配

在结果报告业务中,我们需要根据 mp-html 渲染的 Markdown 内容高度,动态决定是否展示"解锁完整结果"的遮罩。核心挑战在于:

  • 富文本内容高度不固定:包含图片、表格、代码块等多种元素
  • 异步资源加载:远程图片加载导致高度"跳变"
  • 响应式布局:不同屏幕宽度下内容高度不同

2. 传统方案:uni.createSelectorQuery 的局限性

typescript 复制代码
// 常规做法:使用 nextTick + 选择器查询
this.$nextTick(() => {
  uni.createSelectorQuery()
    .select('#content')
    .boundingClientRect(rect => {
      this.contentHeight = rect.height;
    })
    .exec();
});

缺点分析

问题 具体表现 影响
单次快照 仅获取查询时刻的尺寸 图片加载后高度变化无法感知
时机难控 nextTick 时资源可能未加载完成 拿到的是占位符高度
频繁调用 为"实时"需定时轮询 性能开销大

核心痛点:高度跳变

富文本中的图片加载过程:

  1. DOM 解析 → 图片高度为 0 或占位符
  2. 网络请求 → 异步等待
  3. 图片渲染 → 页面重排,高度瞬间变化

createSelectorQuery 只能捕获第 1 步的高度,导致遮罩层定位错误。

3. ResizeObserver 方案

为什么 ResizeObserver 适合 mp-html 场景

ResizeObserver 是浏览器原生 API,专门用于监听元素尺寸变化。对于 mp-html 渲染的富文本场景,它能精准捕捉:

  • 图片加载完成后的高度撑开
  • 字体大小变化导致的行高调整
  • 屏幕旋转引起的宽度变化

代码实现

typescript 复制代码
// #ifdef H5
const observer = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const newHeight = entry.contentRect.height;
    if (newHeight > 0) {
      blocks.value[index].height = newHeight;
      emit("ready");
    }
  }
});

const el = document.getElementById("block-" + index);
if (el) observer.observe(el);
// #endif

4. 优缺点深度分析

✅ 优点

优点 说明
主动监听 无需手动触发,尺寸变化自动回调
异步友好 图片加载完成后的高度变化精准捕捉
高性能 浏览器原生实现,相比 MutationObserver + 轮询更高效
精准 提供 contentRect.height 精确像素值

⚠️ 缺点

缺点 说明 应对方案
H5 专属 仅支持浏览器环境,小程序/App 端不可用 需结合 #ifdef H5 条件编译
兼容性 IE 浏览器不支持 考虑 polyfill 或降级方案
内存泄漏风险 组件销毁时未断开观察 onUnmounted 中调用 observer.disconnect()
触发过于频繁 每次微小的尺寸变化都会触发 结合防抖/节流处理

注意事项

typescript 复制代码
// ❌ 错误:未清理观察者
onUnmounted(() => {
  // 忘记 disconnect 导致内存泄漏
});

// ✅ 正确:组件销毁时断开观察
onUnmounted(() => {
  observer?.disconnect();
});

5. 适用场景判断

场景 推荐方案
H5 环境 + mp-html 动态高度 ✅ ResizeObserver
需要兼容小程序端 ❌ 需降级为 createSelectorQuery + 定时器
静态内容(高度不变) ❌ 无需使用,单次查询即可
简单业务(低频变化) 可用 createSelectorQuery + 定时轮询

6. 总结

在 Uni-app H5 环境下处理 mp-html 富文本的动态高度时,ResizeObserver 是目前最优雅的解决方案。它能完美解决异步图片加载导致的"高度跳变"问题,但需要注意:

  1. 条件编译:仅在 H5 环境下使用
  2. 资源清理:组件销毁时断开观察
  3. 降级兼容:需要考虑不支持 ResizeObserver 的旧版浏览器

通过合理使用 ResizeObserver,可以实现丝滑的 WebView 体验,避免遮罩层错位等问题。

相关推荐
满栀5857 分钟前
状态管理:Redux、Vuex、Pinia 核心区别
前端·javascript·typescript
一拳不是超人44 分钟前
DeepSeek Harness 为什么敢说"一切皆插件"?拆透 Cordis 引擎的五大核心机制
前端·人工智能·agent
IT_陈寒1 小时前
Python的GIL让我多写了500行代码
前端·人工智能·后端
风骏时光牛马1 小时前
AI智能体能力调度微服务
前端
Eloudy3 小时前
ReAct 原理简介
前端·javascript·人工智能·react.js·agent·gpu
ZJU_统一阿萨姆4 小时前
【DSH】如何将 DeepSeek Harness 嵌入生产环境?万字解构 DeepSeek Agent Harness 的运行机制与安全边界
前端·javascript·安全
用户921080262864 小时前
4. 前端地图大量点位实时更新优化:后端推增量,前端做 diff
前端
SoaringHeart4 小时前
Flutter最佳实践:Web项目中文字体首次加载乱码问题解决
前端·flutter
西安小哥5 小时前
破局与重生:大厂前端如何借力 AI 转型“超级全栈“
前端·人工智能
sunly_5 小时前
TypeScript总结:16、面向对象速查
前端·javascript·typescript