Taro开发H5在Safari上遇到的坑

1,273 阅读3分钟

Taro版本:"@tarojs/taro": "3.3.19",

一、Safari底部工具栏遮挡

问题现状:

页面采用flex布局,height: 100vh撑满全部屏幕。在安卓手机浏览器上运行没有问题,但是在Safari上,Safari工具栏会遮挡住图片中红框的部分,只有全屏的模式下才能正常显示全部内容。

// 页面容器
.page-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

image-20220120083112082.png

问题原因:

问题就是出在100vh上,Safari会认为100vh是全屏的高度,导致在工具栏展开时被遮挡了。

解决办法:

1.针对Safari的meta标签,下面两个标签在Taro默认的模板中就是存在的,但是在iPhone12上并没有效果。但如果不是Taro的项目,可以加下试试,姑且写在这里。

<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">

2.将100vh改写成100%,改写后:

// 页面容器
.page-container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

3.这样改了之后发现还是 没有用,继续往上级查找发现<div id="app" class="taro_router">taro编译出来的div.taro_router也使用了100vh。在app.scss写样式覆盖,问题解决。

image-20220120084022156.png

// taro原生是100vh,导致ios下底部按钮被遮挡
.taro_router {
  min-height: 100% !important;
}

二、Safari不显示本地图片

问题现状:

如下面代码所示,按照Taro官方的建议import本地图片,然后放在src属性中。但是Safari中未显示图片。

import avator from '@/assets/icon/avator.png'
​
<Image
width={180}
height={180}
round
fit="contain"
src={avator}
onClick={checkLogin}
/>

问题原因:

不明

解决办法:

// 引入本地图片最好使用相对路径,如果使用@开头的话ios下safari加载失败
import avator from '../../assets/icon/avator.png'

三、使用@antmjs/vantui框架开发,stepper的disable状态在Safari下看不见数字

版本:"@antmjs/vantui": "^1.4.4",

问题现状:

我们使用了vant社区开发的@antmjs/vantui框架,它可以支持多端开发,同时也保持和vantui最大程度上的一致。但是当步进器Stepper的状态为disabled的时候,在Safari浏览器上数字未显示,其他浏览器显示正常。

image-20220120084927990.png

问题原因:

Safari下的input disabled存在默认样式,导致样式重叠。

解决办法:

// IOS下手机safari
input:disabled,
input[disabled] {
    -webkit-text-fill-color: #2c363f;
    opacity: 1;
}
​
input[disabled]::placeholder {
    -webkit-text-fill-color: darkgray;
}

四、使用@antmjs/vantui框架,Dialog弹出多层模态框

版本:"@antmjs/vantui": "^1.4.4",

问题现状:

<View>
  <Dialog id="vanDialog" />
</View>
​
import { Dialog } from "@antmjs/vantui"; 
​
Dialog.alert({
  title: '标题',
  message: '弹窗内容',
}).then(() => {
  // on close
});

按照官网的方式,使用Dialog可能会弹出多层模态框重叠在一起,导致需要关闭多次。

问题原因:

表层原因:页面上存在多个弹框,比如说还有Popup组件,就有可能复现这个问题;

解决办法:

  1. 拆分多个组件,将页面上的内容拆分,一个页面上不出现多个模态框

  2. 动态渲染,尽量保证同一时间只有一个模态框锚点

    {/* 不展示的时候不渲染输入模态框 */}
    {show ? (
        <InputDialog
            show={show}
            {...dialogOption}
            onClose={() => setShow(false)}
         />
    ) : null}
    
  3. 使用组件方式调用Dialog

    {showConfirm ? (
        <Dialog
            show={showConfirm}
            showCancelButton={true}
            onClose={() => setShowConfirm(false)}
            message={`确认删除[${spec.name}]吗?`}
            onConfirm={handleConfirm}
        />
    ) : null}
    

工作中的随笔,如有不正确之处,敬请指正。