H5开发问题汇总
flex不会缩短至小于内容框尺寸导致内容溢出
默认情况下,元素不会缩短至小于内容框尺寸,若想改变这一状况,需要设置元素的min-width与min-height属性
<div class="flex"><div class="f1 minW0">minH0 或 minW0 配合 f1 同时使用</div></div>
.flex {
display: flex;
}
.f1 {
flex: 1;
}
.minH0 {
min-height: 0;
}
.minW0 {
min-width: 0;
}
iOS手机H5下拉遮挡内容问题解决方案
原因:由于iOS的弹性滚动(overscroll)特性导致的,解决方案如下
1、设置meta标签viewport
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover, user-scalable=no" />
2、body宽高100%,并且禁止滚动,解决iOS上拉下拉白色底色遮挡,已经影响功能滚动的问题
html,
body {
/*滚动事件发生在 html 元素上;JS 中可以监听 html 的滚动*/
overflow-y: hidden;
/*body 宽度大 html 度时,某些浏览器会出现内部滚动条;所以设置「html、body」宽度相同且「overflow-x: hidden」*/
overflow-x: hidden;
width: 100%;
/*让 html 和浏览器窗口高度一致*/
height: 100%;
/*少数浏览器默认背景色为浅灰色,所以设置默认背景颜色为纯白*/
background-color: #FFF;
/*取消部分浏览器点击有阴影*/
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
3、功能模块内滚动按需使用以下公共样式处理
.scrollX {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
overflow-x: scroll;
}
.scrollY {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
overflow-y: scroll;
}
iOS系统中transform: translate3d()会超出父级overflow: hidden的限制
iOS的WebKit引擎在处理3D变换时会将元素提升到一个新的渲染层,这会导致:
1.元素脱离常规文档流
2.忽略父容器的溢出裁剪
3.特别是在Safari和iOS WebView中表现明显
/* 添加 z-index 和 will-change 属性 */
.parent {
overflow: hidden;
position: relative;
z-index: 1; /* 创建新的堆叠上下文 */
}
.child {
transform: translate3d(0, 50px, 0);
will-change: transform;
}
高德地图相关问题
高德地图使用html2canvas截屏空白问题,配置WebGLParams可解决
new AMap.Map(this.container, {
// 配置WebGLParams
WebGLParams: {
preserveDrawingBuffer: true,
},
})
配置WebGLParams后会导致修改地图主题无效的问题
// 强制开启webgl,解决地图截屏启用的webgl配置后修改地图主题无效的问题
// @ts-ignore
window.forceWebGL = true
高德地图初始化报警告
Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true
/**
* 优化高德地图初始化并解决 Canvas2D 警告
*/
export const patchCanvasContext = (): void => {
const originalGetContext = HTMLCanvasElement.prototype.getContext
// @ts-ignore
HTMLCanvasElement.prototype.getContext = function (
type: string,
attributes: CanvasRenderingContext2DSettings = {},
): RenderingContext | null {
if (type === '2d') {
// 告诉浏览器这个Canvas会被频繁读取,浏览器会优化内存管理
attributes.willReadFrequently = true
}
return originalGetContext.call(this, type, attributes)
}
}
// 使用,地图实例化前调用
patchCanvasContext()
new AMap.Map(this.container, {
zoom: 13,
center: [116.397428, 39.90923],
...options,
})
jsBridge相关问题
如果android回调是以下方式调用,应避免同时或短时间内多次调用
❗注意:由于回调是异步,如果同时调用或短时间内多次调用会覆盖回调函数,导致前面定义的回调处理失效
// 避免同一时刻多个地方多次与android交互,开发时要注意,尽量避免
export const test = (callback: Function) => {
if (isAndroid) {
// 调用android方法
window.android?.func()
// 回调,此处有大坑
// 如果是多个地方调用,这里的回调会被覆盖,导致无法拿到android返回的结果
window.receiveFunc = (result: any) => {
console.log(result)
callback?.()
}
}
}
App中webview相关
app打开h5出,出了必要参数,顶部、底部安全区域最好是由app通过url传递给h5,h5持久化到store及本地中
// 建议webview全屏,页面全部由H5处理
// app在webview中首次打开H5需要在url中传递参数
token // app登录的token,bearer eyJhbGci****
sat // 顶部状态栏安全区域高度 (不传默认0)(为处理部分老机型兼容性问题)
sab // 底部安全区域高度(不传默认0)(为处理部分老机型兼容性问题)
// 全局变量
:root {
--safe-area-inset-top: constant(safe-area-inset-top);
--safe-area-inset-top: env(safe-area-inset-top);
--safe-area-inset-bottom: constant(safe-area-inset-bottom);
--safe-area-inset-bottom: env(safe-area-inset-bottom);
}
// 覆盖vant-ui中顶部安全区域
.van-safe-area-top.van-safe-area-top {
padding-top: var(--safe-area-inset-top);
}
// 覆盖vant-ui中底部安全区域
.van-safe-area-bottom.van-safe-area-bottom {
padding-bottom: var(--safe-area-inset-bottom);
}
// 定义业务中顶部安全区域全局样式类
.safeAreaTop {
padding-top: var(--safe-area-inset-top);
}
// 定义业务中底部安全区域全局样式类
.safeAreaBottom {
padding-bottom: var(--safe-area-inset-bottom);
}
const route = useRoute()
// 顶部、底部安全区域高度
const safeAreaTop = ref<number>(0)
const safeAreaBottom = ref<number>(0)
const setSafeAreaSize = () => {
const top = route.query?.sat?.toString()
const bottom = route.query?.sab?.toString()
if (top) {
setSafeAreaTop(+top)
safeAreaTop.value = +top
} else {
safeAreaTop.value = globalState.safeAreaTop
}
if (bottom) {
setSafeAreaBottom(+bottom)
safeAreaBottom.value = +bottom
} else {
safeAreaBottom.value = globalState.safeAreaBottom
}
try {
document.body.style.setProperty('--safe-area-inset-top', `${safeAreaTop.value}px`)
document.body.style.setProperty('--safe-area-inset-bottom', `${safeAreaBottom.value}px`)
} catch (error) {
}
}
import { defineStore } from 'pinia'
// 全局变量
const STORE_KEY = 'globalStore'
const useGlobalStore = defineStore(
STORE_KEY,
() => {
const globalState = reactive({
// 顶部安全区域高度
safeAreaTop: 0,
// 底部安全区域高度
safeAreaBottom: 0,
})
const setSafeAreaTop = (height: number) => {
globalState.safeAreaTop = height
}
const setSafeAreaBottom = (height: number) => {
globalState.safeAreaBottom = height
}
return {
globalState,
setSafeAreaTop,
setSafeAreaBottom,
}
},
// 开启数据持久化
{
persist: {
key: STORE_KEY,
storage: localStorage,
}
}
)
export default useGlobalStore