Logo

H5 踩坑日记

avatar zixi 15 Aug 2024

H5 踩坑日记

移动端 H5 页面和 PC 端页面开发虽然用到的技术栈一样,但移动端 H5 页面需要注意的问题比 PC 端要多得多,尤其是兼容性的问题,IOS 和 安卓之间的差异性,安卓机不同版本的机型,为了兼容绝大部分用户,往往需要适配不同版本的机型,下面就我在开发项目过程中出现的问题进行总结(基于 Vue 框架下的代码)。

1. IOS 键盘唤起后收起页面不归位

问题描述:

在 IOS 设备上,键盘弹出,页面整体内容上移,但键盘收起后页面内容不下滑。

问题分析

固定定位的元素,在元素内 input框聚焦的时候,弹出的软键盘占位,失去焦点的时候软键盘消失,但软键盘还是占位的,导致 input 框不能再次输入。

解决办法

在失去焦点时重置滚动元素的滚动位置。

<script lang="ts" setup>
import { get } from 'lodash-es';

function handleBlur() {
  const isIOS = /(iPhone|iPad|MacWechat)/i.test(get(window.navigator, 'userAgent', 'node'));
  if (isIOS) {
    setTimeout(() => {
      const scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0;
      const scrollY = scrollHeight > 1 ? scrollHeight - 1 : scrollHeight + 1;
      window.scrollTo(0, scrollY);  // 让页面滚动一像素
    }, 200);
  }
}
</script>

<template>
	<input @focus="handleFocus" @blur.prevent="handleBlur" />
</template>

拓展知识

position: fixed 在 IOS 中,收起键盘会被顶上去,特别是在第三方键盘中。

2. iOS 上 sticky 元素遮挡滚动条

问题描述:缺少原因分析

在 iOS 设备上,使用 position: sticky 的元素会遮挡滚动条,导致页面效果不美观。

sticky-bug.png

问题分析

这主要与 IOS 的兼容性有关:position: sticky 元素的行为与其最近的可滚动祖先元素有关。在 iOS 上,如果 sticky 元素的滚动容器(祖先元素)具有 overflow: scrolloverflow: auto,可能会出现意外的定位行为。例如,iOS 上可能会发生 sticky 元素在滚动时表现异常,或者被滚动条遮挡。

解决办法:

overflow-y: scroll 应用于 .container 元素即可解决这个问题。

<template>
  <div class="page">
    <!-- other code.... -->
    <div class="container">
      <div class="sticky-box">sticky-box</div>
      <div class="content height">height: 1200PX</div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.page {
  width: 100%;
  height: 100vh;
  padding-bottom: 56px;
  overflow-y: scroll;
  text-align: center;
  background-color: #fff;
}

.container {
  padding-top: 100px;

  .sticky-box {
    position: sticky;
    z-index: 99;
    top: 0;
    line-height: 50px;
    background-color: #fafafa;
    box-shadow: 0px 4px 18px 2px rgba(4, 0, 0, 0.1);
  }

  .content {
    height: 1200px;
    padding: 40px;
    background-color: #fafafa;
  }
}
</style>

3. IOS滚动不流畅

解决办法:

在滚动的元素上添加CSS

overflow-y: auto;
-webkit-overflow-scrolling : touch;

在iOS 13之后,不需要再设置-webkit-overflow-scrolling:touch了,因为所有可滚动的框架,或者设置 overflow 滚动的元素默认都是弹性效果了

4. flex-1 的后代元素无法获取高度

问题分析:

在使用 CSS 的 flexbox 布局时,flex: 1 表示一个弹性项目将占据父容器的可用空间,以实现自动调整大小的效果。然而,有时候在某些情况下,设置 flex: 1 并不足以使子元素的高度生效。这是因为在默认情况下,弹性项目的高度是由其内容的高度决定的,而不是由父容器撑开。

解决办法:

添加 height: 0 是为了确保父容器的高度为 0,然后使用 flex: 1 将父容器的高度撑开,最后通过设置子元素的 align-self: stretch 和 height: 100% 来使子元素的高度与父容器一致。

.page{
  display: flex;

  .parent {
    flex: 1,
    height: 0;

    .children {
      height: 100%; /* height 设置生效 */
    }
  }
}

5. 解决 iOS 微信 H5 页面分享失败的问题:hash 模式下分享失败:

问题描述:

Vue 中路由使用 hash 模式,开发微信 H5 页面分享时在安卓上设置分享成功,但是 IOS 的分享异常, IOS 当前页面分享给好友,首次进入页面展示正常,如果二次分享,则跳转到首页;使用 Vue Router 跳转到第二个页面后在分享时,分享设置失败;但以上在安卓上分享都显示正常。
ios-share-bug.png

问题分析:

  1. iOS 微信内置浏览器对 hash 的处理:
    iOS 微信内置浏览器可能在分享时忽略 URL 中的 hash 部分,导致分享的链接在其他设备上打开时,hash 信息丢失。这就可能导致二次分享或者重新打开链接时,无法正确解析路由,导致跳转到首页。
  2. 二次分享跳转到首页:
    当页面通过 hash 模式设置路由后,iOS 微信在生成分享链接时,可能将 hash 部分剥离掉,导致分享的 URL 没有包含正确的路由信息。在用户二次分享时,由于 URL 不完整,默认会跳转到首页。
  3. 在 Vue Router 跳转到第二个页面后分享失败:
    当你从一个页面跳转到另一个页面时,如果没有正确更新微信 JS-SDK 的配置(比如调用 wx.config),可能会导致分享设置失败。这是因为微信需要每次在页面加载或路由变化时重新配置 JS-SDK 以确保分享的内容是正确的。

解决办法:

  1. 在路由跳转后重新初始化微信 JS-SDK:
    确保每次路由切换后都重新调用 wx.config,并设置分享内容。你可以在每次路由切换完成后(例如使用 router.afterEach)重新进行微信分享配置。

    router.afterEach((to, from) => {
      // 在这里调用 wx.config 并设置分享参数
    });
    
  2. 处理 iOS 分享链接
    在生成分享链接时,可以手动拼接参数,避免微信自动处理 URL 导致 hash 丢失。你可以在分享时使用完整的 URL(包括 query 参数)来代替 hash。

    let url = location.href.split('#')[0]; // 获取当前页面 URL,去掉 hash
    let fullUrl = `${url}?path=${encodeURIComponent(to.fullPath)}`; // 拼接分享的完整链接
    
  3. 监控微信浏览器环境并做兼容处理
    在代码中检测是否为微信浏览器,并根据不同的平台做兼容处理,例如对 iOS 的分享逻辑进行单独处理。
  4. 使用 history 模式来替代 hash 模式:
    君子不立于危墙之下,如果可以,建议将 Vue Router 的模式切换为 history 模式,这样分享时 URL 中不会有 #,能够更好地兼容 iOS 和 Android。

6. 解决 iOS 微信 H5 页面分享失败的问题:分享配置在多页面间的正确处理方法

问题描述:

假设有:PageA、PageB、PageC,其中 PageA 和 PageC 需要打开分享、PageB 需要关闭分享,根据 jssdk 隐藏功能按钮接口文档 我们在 PageB中设置 hideMenuItems

此时,当你从 PageB 页面前往任意页面都将发现分享失效

问题分析:

理论上你触发关闭了之后如果不重新设置 showMenuItems,其它页面也是没有分享内容的。

解决办法:

  1. 在每个页面的路由配置中,分别设置 wx.config 和 wx.ready,确保每次进入页面时重新初始化微信分享配置。
  2. 我们可以在每次进入页面时都执行showMenuItems :
    showMenuItems-config.png
  3. 离开 PageB 页面的时候重新开放 showMenuItems 配置(注:需要在页面初始化的时候就注册好 api ):
    beforeRouteLeave(to, from, next) {
     wx.showMenuItems({
       menuList: ['menuItem:share:appMessage', 'menuItem:share:timeline', 'menuItem:share:qq', 'menuItem:share:weiboApp', 'menuItem:share:facebook', 'menuItem:share:QZone']
     });
     next();
    }
    

总结:

微信 H5 开发涉及诸多知识点,比如登录授权、JS-SDK 授权等等。然而,在这里我们仅仅讨论了分享功能的配置。事实上,H5 项目中的“坑”远不止这些,每一个细节都可能隐藏着复杂的挑战。开发的旅程就是在不断探索中前行,正所谓生命不息,踩坑不止……

Tags
H5
IOS