移动端的兼容问题

1、ios下input为type=button属性disabled设置true,会出现样式文字和背景异常问题。

解决方案:使用opacity=1来解决

2、对非可点击元素如(label,span)监听click事件,部分ios版本下不会触发。

解决方案:css增加cursor:pointer就搞定了

3、input为fixed定位,在ios下input固定定位在顶部或者底部,在页面滚动一些距离后,点击input(弹出键盘),input位置会出现在中间位置。

解决方案:内容列表框也是fixed定位,这样不会出现fixed错位的问题

4、移动端字体小于12px使用四周边框或者背景色块,部分安卓文字偏上bug问题。

解决方案:可以使用整体放大1倍(width、height、font-size等等)再使用transform缩放,使用canvas在移动端会模糊也需要这样的解决方案

5、在移动端图片上传图片兼容低端机的问题。

解决方案:input 加入属性 accept="image/*" multiple

6、在安卓机上placeholder文字设置行高会偏上

解决方案:input有placeholder情况下不要设置行高

7、overflow:scroll,或者auto在iOS上滑动卡顿的问题

解决方案:加入-webkit-overflow-scrolling:touch;

8、iphonex的适配

解决方案:

 

body{    
    padding-top: constant(safe-area-inset-top);
    padding-top: env(safe-area-inset-top);
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);

}

9、IOS移动端click事件300ms的延迟响应

解决方案:

fastclick可以解决在手机上点击事件300ms的延迟

window.addEventListener( "load", function() {

  FastClick.attach( document.body );

}, false );

10、CSS动画页面闪白,动画卡顿

解决方法:

①尽可能地使用合成属性transform和opacity来设计CSS3动画,不使用position的left和top来定位

②开启硬件加速

  -webkit-transform: translate3d(0, 0, 0);

    -moz-transform: translate3d(0, 0, 0);

      -ms-transform: translate3d(0, 0, 0);

          transform: translate3d(0, 0, 0);

11、阻止旋转屏幕时自动调整字体大小

解决方案:html, body, form, fieldset, p, div, h1, h2, h3, h4, h5, h6 {    -webkit-text-size-adjust:none;}

12、解决iphone下选中input页面自动放大的问题,viewport的user-scalable要设置成no

解决方案:

13、html5调用安卓或者ios的拨号功能

解决方案:html5提供了自动调用拨号的标签,只要在a标签的href中添加tel:就可以了。

点击可拨打电话:11111111111
400-810-6999 转 1034
window.location.href = 'tel:11111111111';
点击可发送短信
点击可发送短信

14、不让 Android 手机识别邮箱

解决方案:

15、禁止 iOS 识别长串数字为电话

解决方案:

16、禁止 iOS 弹出各种操作窗口

解决方案:-webkit-touch-callout:none

17、消除 transition 闪屏

解决方案:

 .box { 
       -webkit-transform-style: preserve-3d; 
       -webkit-backface-visibility: hidden; 
       -webkit-perspective: 1000; 
  }

18、iOS 系统中文输入法输入英文时,字母之间可能会出现一个六分之一空格可以通过正则去掉

解决方案:this.value = this.value.replace(/\u2006/g, '');

19、禁止ios和android用户选中文字

解决方案:-webkit-user-select:none

20、fixed定位缺陷

ios下fixed元素容易定位出错,软键盘弹出时,影响fixed元素定位

android下fixed表现要比iOS更好,软键盘弹出时,不会影响fixed元素定位

ios4下不支持position:fixed

解决方案: 可用iScroll插件解决这个问题

21.1px在移动端的解决方案

推荐解决方案:

1).媒体查询 + transfrom 对方案1的优化

/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.5);
        transform: scaleY(0.5);
    }
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.33);
        transform: scaleY(0.33);
    }
}

2).box-shadow方案

div {
    -webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);
}

3).viewport + rem 

// head

// js
var viewport = document.querySelector("meta[name=viewport]")
if (window.devicePixelRatio == 1) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
} 
if (window.devicePixelRatio == 2) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
} 
if (window.devicePixelRatio == 3) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
} 
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;

22.移动端实现,键盘点击,用户唤起搜索功能(即enter键?)
解决方案:


Tips:

1.不管是安卓还是苹果手机,搜索按键的keycode都是13,这里是vue项目,可以使用按键修饰符。
2.用type="search"来统一安卓和苹果机的搜索按键。
3.必须在input标签外面套上form表单,并设置 action=“javascript:void 0”,action属性很关键,才能4.实现搜索功能,不能省略。
5.若想添加自动聚焦功能,可以先获取当前input这个dom元素,再添加focus()方法;
 

this.$nextTick(() => {
    this.$refs.searchInput.focus()
})

23.safari浏览器(包含ios的微信浏览器,一个内核)在ios中返回上一级不会刷新页面,但是安卓会重新刷新页面

解决方案:
(1)针对这种问题,当时的产品的方案是要保留缓存,返回上一级页面时,会记住用户的筛选记录,对于安卓端的刷新页面的现象,当时的解决方案是将用户的筛选条件记录在sessionStorage里面,当返回上一级页面时,从缓存中读取记录,并重新请求。在监听用户跳转页面的行为中,存在两种情况:

一种是vue内置的vue-router路由跳转
一种是js里面使用window.lcaotion.href跳转
针对这两种跳转方式,在使用监听事件onbeforeunload时,引出了兼容性问题24
(2)针对safari不想留住缓存的情况,渴望刷新,新增解决方案:
监听页面的pageshow事件

if(isIOS()){
	  window.addEventListener('pageshow', function (event) {
	        if (event.persisted || window.performance &&
	                window.performance.navigation.type == 2)
	        {
	            location.reload();
	        }
	    },false);
}

24.微信浏览器移动端不支持window.open打开新的窗口,不支持onbeforeunload页面卸载事件

解决方案:
在监听页面地址变化的时候,我开始使用的是onbeforeunload事件,用来针对vue-router跳转和window.location.href跳转两种情况都很有效果。是在使用谷歌浏览器内置的移动端模拟器上面是好的,当我用手机真机调试的时候,竟然没有效果!!!!

所以,我不得不放弃了这个onbeforeunload。
最后,分成了两种来判断,vue-router跳转使用路由内置的钩子函数beforeRouteLeave来添加(这个监听不到window.location.href跳转);
window.location.href则在添加跳转的事件里面捕获;

另外,提一嘴,H5新增的历史记录监听事件,通用性感觉不高:

window.onpopstate:当调用history.go()、history.back()、history.forward()浏览器的几个前进后退时触发;pushState()\replaceState()方法不触发(vue-router实现原理)
window.onhashchange:当前 URL 的锚部分(以 ‘#’ 号为开始) hash值发生改变时触发
另外补充一点:

使用onpagehide可以检测浏览器页面的关闭事件触发,以及监听页面window.location.href的跳转事件,但是对于vue的单页面router跳转是捕捉不到的,可以使用destoryed或者beforeRouteLeave路由的钩子函数来监听

或者onunload也是可以尝试使用的方法之一

25.在移动端浏览器中(至少在微信环境中),打开http://XXXX.pdf预览pdf文件,ios可以直接预览,安卓必须先跳转浏览器下载后才能看

解决方案:引入pdfh5.js插件,跳转另外一个html网站的链接页面,在这个页面中创建一个dom,支持使用canvas和svg两种渲染模式,进行预览

npm install --save pdfh5





//*********************************或者js引入****************************
//1.引入css

//2.创建div
//3.依次引入js //4.实例化 var pdfh5 = new Pdfh5('#demo', { pdfurl: "./default.pdf" });

26.ios微信首次打开h5页面,底部是没有历史记录导航的,如果这时候直接跳转外链,再返回,这时首页底部就会增加历史记录导航,而且出现的问题是=》遮挡首页底部部分内容(商城首页)

解决方案:手动增加一个空的历史记录

/**
 * 判断是否为ios
 */
export function isIOS () {
  return !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
}
/**
 * 微信浏览器判断
 */
export function isWXBrowser () {
  var ua = window.navigator.userAgent.toLowerCase()
  if (ua.match(/MicroMessenger/i) == 'micromessenger') return true
  return false
}

if (isIOS() && isWXBrowser()) {
      window.history.pushState({}, '', '')
}

27.ios在微信浏览器中的h5网页有页面的回弹效果,若页面中存在轮播的swiper组件,滑动过程中会出现页面抖动

解决方案:监听页面的滑动事件,在滑动触发的时候,停止轮播的动画

28.苹果低版本的手机上不支持获取使用dom.scrollTo(0,0),使用该方法会报错。

解决方案:使用dom.scrollTop=0,就可以正常使用

29.移动端文字实现两端对齐,使用text-align-last在ios会有兼容性问题

使用text-align-last:justify;在安卓上面表现没有问题,但是在ios上面不会对齐。
解决方案:在当前的元素后面添加一个after伪类,并给当前的元素设置行高为0,如下:

span{
	text-align: justify;
    text-align-last: justify;
	line-height:0px;
	&::after{
		content:"";
	    width:100%;
	    display:inline-block;
	}
}

30.移动端安卓和ios对于格式化时间new Date()日期格式的处理兼容性问题

const strTime="2020-1-1 19:10:10";
const myDate = new Date(strTime);
const Y = myDate.getFullYear();
const M = myDate.getMonth()+1;
const D = myDate.getDate();
const curDay = Y + '-'+ M + '-' + D;
console.log(curDay)
// 输出结果:Android系统:2020-1-1           iOS 系统:NaN-NaN-NaN 

解决方案:使用字符串的替换,将 ”-“替换为 ”/“,这样ios和安卓就都可以支持了

const strTime="2018-1-1 9:10:10";
var date= new Date(Date.parse(strTime.replace(/-/g,  "/")));  //转换成Data(); 

31.安卓和ios在调用微信的jssdk的时候的区别,批量隐藏\显示菜单时灵时不灵问题

解决方案:

安卓:当你在当前页面使用wx.hideMenuItems(),会把你想要隐藏的菜单隐藏起来,当你跳转到新的页面时(也就是重新调用wx.config后),你的隐藏了的菜单又会被重新显示出来,需要重新调用wx.hideMenuItems(),再次把你想要隐藏的菜单隐藏起来
ios:当你在当前页面使用wx.hideMenuItems(),会把你想要隐藏的菜单隐藏起来,当你跳转到新的页面时(也就是重新调用wx.config后),你在上一个页面隐藏的菜单还会继续保持隐藏的状态。如果这个时候你想让之前隐藏的菜单展示出来,就必须调用 wx.showMenuItems() 方法去设置要显示出来的菜单,才能实现这个需求

32.软键盘与输入框问题
h5页面有个问题就是,当输入框在最底部,点击软键盘后输入框会被遮挡。可采用如下解决方案

var oHeight = $(document).height(); //浏览器当前的高度
   
$(window).resize(function(){
    if($(document).height() < oHeight){
        $("元素").css("position","static");
    }else{
        $("元素").css("position","absolute");
    }    
});



另一软键盘输入框问题,也可视为fixed定位失败问题,ios下fixed元素容易定位出错,软键盘弹出时,影响fixed元素定位
虽然 isScroll.js 可以很好的解决 fixed 定位滚动的问题,但是不在万不得已的情况下,我们尽量尝试一下不依赖第三方库的布局方案,以简化实现方式。

解决思路:
既然在 iOS 下由于软键盘唤出后,页面 fixed 元素会失效,导致跟随页面一起滚动,那么假如——页面不会过长出现滚动,那么即便 fixed 元素失效,也无法跟随页面滚动,也就不会出现上面的问题了。配合移动端页面滚动滞涩感的解决思路css在body元素上添加-webkit-overflow-scrolling: touch;
如果考虑到更老一些的 iOS 系统不支持 fixed 元素,完全可以把 fixed 替换成 absolute 。测试后效果是一样的。

谈到了 iOS ,也来简单说一下 Android 下的布局吧。

在 Android2.3+ 中,因为不支持 overflow-scrolling ,因此部分浏览器内滚动会有不流畅的卡顿。但是目前发现在 body 上的滚动还是很流畅的,因此使用第一种在 iOS 出现问题的 fixed 定位的布局就可以了。

如果需要考虑 Android2.3 以下系统,因为不支持 fixed 元素,所以依然要需要考虑使用 isScroll.js 来实现内部滚动。

其实在 fixed 和输入框的问题上,基本思路就是: > 由于 fixed 在软键盘唤起后会失效,导致在页面可以滚动时,会跟随页面一起滚动。因此如果页面无法滚动,那么 fixed 元素即使失效,也不会滚动,也就不会出现 bug 了。

所以可以在这个方面去考虑解决问题。

至此一个不依赖第三方库的 fixed 布局就完成了

// 处理iOS 微信客户端弹窗状态下调起输入法后关闭输入法页面元素错位解决办法
    var ua = window.navigator.userAgent.toLowerCase();
    if (/iphone|ipod|ipad/i.test(navigator.appVersion) && /MicroMessenger/i.test(ua)) {
      document.body.addEventListener('focusout', () => {
        console.log('focusout')
        window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
      });
    }
    //或者:
    scrollto0() {
      window.scrollTo(0, 0);
    }

32.1输入框在页面较底部时,安卓手机弹出的键盘会遮挡且点击原生键盘的关闭按钮收回键盘时,输入框没有失焦 

解决方案:

Element.scrollIntoView()和Element.scrollIntoViewIfNeeded()方法让当前的元素滚动到浏览器窗口的可视区域内。

使用Element.scrollIntoView()和Element.scrollIntoViewIfNeeded()解决遮挡问题,监听输入框聚焦事件,调用上面的方法将激活的元素(输入框)滚动到可视区域

通过监听页面resize事件来解决点击原生键盘的关闭按钮收回键盘时,输入框没有失焦的问题

可参考以下代码(使用vue实现)

data() {
    return {
        originHeight: 0,
        isAndroid:
            /Android/gi.test(navigator.userAgent) ||
            /adr/gi.test(navigator.userAgent),
        resizeTimer: null
    };
},
methods: {
    resizeFn() {
        // 防止部分手机触发两次resize事件导致无法拉起键盘
        if (this.resizeTimer) return;
        this.resizeTimer = setTimeout(() => {
            let resizeHeight =
                document.documentElement.clientHeight ||
                document.body.clientHeight;
            if (this.originHeight > resizeHeight) {
                // 拉起键盘会有动画,所以需要加延时,否则不管用
                setTimeout(() => {
                    if ("scrollIntoView" in document.activeElement) {
                        document.activeElement.scrollIntoView();
                    } else {
                        document.activeElement.scrollIntoViewIfNeeded();
                    }
                }, 0);
            } else {
                document.activeElement.blur();
                document.removeEventListener("resize", this.resizeFn);
            }
            clearTimeout(this.resizeTimer);
        }, 100);
    }
},
mounted() {
    if (this.isAndroid) {
        this.originHeight =
            document.documentElement.clientHeight ||
            document.body.clientHeight;
        window.addEventListener("resize", this.resizeFn);
    }
}

33.修改移动端的点击高亮效果

解决方案:

* {-webkit-tap-highlight-color:rgba(0,0,0,0);}

34.移动端某些情况下input的placeholder会出现文本位置偏上的现象:

解决方案:PC端设置line-height等于height能够对齐,而移动端仍然是偏上,解决是设置line-height:normal

35.IOS上click点击事件会有300ms的延迟响应:

解决方案:引入fastclick.js解决

36.音视频问题

自动播放

  1. ios safariiPhone Safari中不支持,但在webview中可能被开启;iOS开发文档明确说明蜂窝网络下不允许autoplay;
  2. chrome中,设置mouted后可以自动播放
  3. 微信中不允许自动播放。但是可以借助WeixinJSBridge实现

单例问题

ios safari中的音频对象是单例的,ios中是无法播放多个音频文件的

循环播放

ios部分机型不支持循环播放

解决方案:监听播放完成事件ended,手动触发播放




    Looping Audio
    


    


video

  1. preload,ios下是不支持的。通用的方法是对视频进行play()后立即停止
  2. ios视频自动全屏播放:设置内联属性playsinline webkit-playsinline

37.海报生成-html2Canvas

营销场景和裂变过程中,我们需要将页面内容一部分作为图片整体分享出去。大部分情况下会用到

html2Canvas

如果只是简单的二维码加海报图,建议直接用drawImg,而不是用和这个插件

图片跨域

解决方案:需设置useCORS:true

  1. html2canvas提供的proxy方案
    await html2canvas(eleImgBox, {
      // 前提是,请求的图片本身是支持跨域请求的(可能需要后端设置)
      proxy: 'https://aliyun-oss.61info.cn'
    })
  1. nginx做域名转发即可
  2. 像二维码这种,可以考虑base64格式的图片

38. ios的body设置overflow:hidden仍然可以滚动

解决方案:一般在所有元素最外层再包一个大盒子.wrap

  .wrap{
      position:relative;
      overflow:hidden;
  }

39.禁止复制、选中文本

解决方案:解决移动设备可选中页面文本(视产品需要而定)

Element {
  -webkit-user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
   user-select: none;
}

40.长时间按住页面出现闪退

element {
  -webkit-touch-callout: none;
}

41.设置缓存

手机页面通常在第一次加载后会进行缓存,然后每次刷新会使用缓存而不是去重新向服务器发送请求。如果不希望使用缓存可以设置no-cache。

42.浏览器私有及其它meta

以下属性在项目中没有应用过,可以写一个demo测试以下!

QQ浏览器私有

全屏模式


强制竖屏


强制横屏


应用模式


UC浏览器私有

全屏模式


强制竖屏


强制横屏


应用模式


其它

针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓


微软的老式浏览器


windows phone 点击无高光

43.IOS键盘字母输入,默认首字母大写

解决方案:设置如下属性

44.移动端 HTML5 audio autoplay 失效问题

这个不是 BUG,由于自动播放网页中的音频或视频,会给用户带来一些困扰或者不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放,必须由用户来触发才可以播放。

解决方法思路:先通过用户 touchstart 触碰,触发播放并暂停(音频开始加载,后面用 JS 再操作就没问题了)。

解决方案:

document.addEventListener('touchstart', function () {
  document.getElementsByTagName('audio')[0].play();
  document.getElementsByTagName('audio')[0].pause();
});

45.ios手机父元素设置了overflow:hidden和border-radius,子元素超出部分不隐藏

在父元素加transform: rotate(0deg)属性

.father {
    transform: rotate(0deg)
}

46.ios手机页面滚动时动画停止 

给动画元素设置transform: translate3d(0, 0, 0);

.animation {
    transform: translate3d(0, 0, 0);
}

47.ios手机上input输入框设置opacity会导致聚焦拉起键盘时,不会把输入框挤到可视区域

原因:

设置opacity小于等于0.01时,就会出现这个问题

解决方案:

设置opacity大于0.01

.box {
    opacity:0.011
}

 48.vite3创建的vue项目本地开发服务在ios12.1及以下版本的手机上白屏

原因:

globalThis为undefined的原因,globalThis的兼容性

解决方案:

给在入口的html文件将globalThis指向window

49.ios手机上将图片转成base64失败(感谢国梁同学提供此问题)

原因:

转换需要给图片设置允许跨域,但是在ios手机上允许跨域和给src赋值有顺序的区别,在chrome模拟没顺序问题

解决方案:

先给Image对象设置允许跨域,再给Image对象的src赋值

50.vite 创建的项目使用可选链操作符(?.)本地启动服务在 ios13.4 以下版本的手机白屏报错

原因:

vite 在启动本地服务时,只处理语法转译不包含 polyfill,可选链操作符语法在 ios13.4 以下版本不支持,所以会报错白屏

解决方案:

使用rollup-plugin-esbuild将可选链操作符语法降级到兼容低版本浏览器。如果是生产环境使用*@vitejs/plugin-legacy*

npm install rollup-plugin-esbuild -D
// vite.config.ts
import vue from "@vitejs/plugin-vue";
import legacy from "@vitejs/plugin-legacy";
import esbuild from "rollup-plugin-esbuild";

export default defineConfig(({ command }) => {
    const plugins = [vue()];
    if (command === "build") {
        plugins.push(
            legacy({
                targets: ["Android >= 8", "iOS >= 10"],
            })
        );
    }
    if (command === "serve") {
        plugins.push(
            esbuild({
                target: "ios12",
                loaders: { ".vue": "js", ".ts": "js" },
            })
        );
    }
    return {
        plugins,
    };
});

你可能感兴趣的:(前端优化,ios,性能优化,前端)