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 体验,避免遮罩层错位等问题。

相关推荐
miss14 分钟前
AI 改完不敢上线?OpenSpec 规约驱动开发实战
前端·代码规范·前端工程化
AiMan1 小时前
腾讯ima还是不可以导出左侧所有对话,只能单条导出,方法不对吗
前端
去伪存真1 小时前
并发量一高就装死?Agent 全链路“防猝死”手册
前端·agent
Moment1 小时前
AI 编程时代,聊聊我的 Mac mini 双屏桌面
前端·后端
AiMan1 小时前
先确认能不能一次把Microsofat Copilot所有内容打包一个文件导出
前端
总要学点什么1 小时前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
上海懒图科技2 小时前
工厂厂区电子地图定位导航:厂区人车精准定位,安全合规双保障
前端·arcgis·vue
西安小哥2 小时前
端侧跑大模型,真正的门槛不在参数量:一次 596 秒到 10 秒的压缩路径复盘
前端·人工智能
陈随易2 小时前
Cloudflare 出钱,Vite 团队挑人,44 个维护者分 30 万美元
前端·后端·程序员
恋猫de小郭3 小时前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter