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

相关推荐
zhangjikuan891 小时前
在 ArkTS 中,Promise 的使用比 TypeScript 更严格(必须显式指定泛型类型)
前端·javascript·typescript
Highcharts.js1 小时前
React 如何实现大数据量图表(性能优化指南)
前端·javascript·react.js·信息可视化·集成·highcharts
奔跑的呱呱牛2 小时前
如何设计一个可扩展的地图前端架构?从0到1的工程实践(OpenLayers)
前端·架构·openlayers
Dxy12393102162 小时前
JS如何把数据添加到列表中
前端·javascript·vue.js
芒果大胖砸2 小时前
uniapp 在h5中预览pdf hybrid方法
pdf·uni-app
清音啊2 小时前
Uniapp 实现左滑显示操作按钮的列表(适配多端 + 实战案例)
uni-app
蜡台2 小时前
Uniapp 实现 二手车价格评估 功能
前端·javascript·uni-app·估值·汽车抵押·二手车评估
旭久2 小时前
web前端开发好物推荐-(code-inspector-plugin/react-dev-inspector)页面快捷定位代码位置
前端·react.js·前端框架