解决方案:使用opacity=1来解决
解决方案:css增加cursor:pointer就搞定了
解决方案:内容列表框也是fixed定位,这样不会出现fixed错位的问题
解决方案:可以使用整体放大1倍(width、height、font-size等等)再使用transform缩放,使用canvas在移动端会模糊也需要这样的解决方案
解决方案:input 加入属性 accept="image/*" multiple
解决方案:input有placeholder情况下不要设置行高
解决方案:加入-webkit-overflow-scrolling:touch;
解决方案:
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);
}
解决方案:
fastclick可以解决在手机上点击事件300ms的延迟
window.addEventListener( "load", function() {
FastClick.attach( document.body );
}, false );
解决方法:
①尽可能地使用合成属性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);
解决方案:html, body, form, fieldset, p, div, h1, h2, h3, h4, h5, h6 { -webkit-text-size-adjust:none;}
解决方案:
解决方案:html5提供了自动调用拨号的标签,只要在a标签的href中添加tel:就可以了。
点击可拨打电话:11111111111
400-810-6999 转 1034
window.location.href = 'tel:11111111111';
点击可发送短信
点击可发送短信
解决方案:
解决方案:
解决方案:-webkit-touch-callout:none
解决方案:
.box {
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
}
解决方案:this.value = this.value.replace(/\u2006/g, '');
解决方案:-webkit-user-select:none
ios下fixed元素容易定位出错,软键盘弹出时,影响fixed元素定位
android下fixed表现要比iOS更好,软键盘弹出时,不会影响fixed元素定位
ios4下不支持position:fixed
解决方案: 可用iScroll插件解决这个问题
推荐解决方案:
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;
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()
})
解决方案:
(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);
}
解决方案:
在监听页面地址变化的时候,我开始使用的是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也是可以尝试使用的方法之一
解决方案:引入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"
});
解决方案:手动增加一个空的历史记录
/**
* 判断是否为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({}, '', '')
}
解决方案:监听页面的滑动事件,在滑动触发的时候,停止轮播的动画
解决方案:使用dom.scrollTop=0,就可以正常使用
使用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;
}
}
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();
解决方案:
安卓:当你在当前页面使用wx.hideMenuItems(),会把你想要隐藏的菜单隐藏起来,当你跳转到新的页面时(也就是重新调用wx.config后),你的隐藏了的菜单又会被重新显示出来,需要重新调用wx.hideMenuItems(),再次把你想要隐藏的菜单隐藏起来
ios:当你在当前页面使用wx.hideMenuItems(),会把你想要隐藏的菜单隐藏起来,当你跳转到新的页面时(也就是重新调用wx.config后),你在上一个页面隐藏的菜单还会继续保持隐藏的状态。如果这个时候你想让之前隐藏的菜单展示出来,就必须调用 wx.showMenuItems() 方法去设置要显示出来的菜单,才能实现这个需求
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);
}
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);
}
}
解决方案:
* {-webkit-tap-highlight-color:rgba(0,0,0,0);}
解决方案:PC端设置line-height等于height能够对齐,而移动端仍然是偏上,解决是设置line-height:normal
解决方案:引入fastclick.js解决
ios safari
iPhone Safari中不支持,但在webview中可能被开启;iOS开发文档明确说明蜂窝网络下不允许autoplay;mouted
后可以自动播放WeixinJSBridge
实现ios safari中的音频对象是单例的,ios中是无法播放多个音频文件的
ios部分机型不支持循环播放
解决方案:监听播放完成事件ended
,手动触发播放
Looping Audio
play()
后立即停止playsinline webkit-playsinline
营销场景和裂变过程中,我们需要将页面内容一部分作为图片整体分享出去。大部分情况下会用到
html2Canvas
如果只是简单的二维码加海报图,建议直接用drawImg,而不是用和这个插件
解决方案:需设置useCORS:true
html2canvas
提供的proxy
方案 await html2canvas(eleImgBox, {
// 前提是,请求的图片本身是支持跨域请求的(可能需要后端设置)
proxy: 'https://aliyun-oss.61info.cn'
})
解决方案:一般在所有元素最外层再包一个大盒子.wrap
.wrap{
position:relative;
overflow:hidden;
}
解决方案:解决移动设备可选中页面文本(视产品需要而定)
Element {
-webkit-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;
}
element {
-webkit-touch-callout: none;
}
手机页面通常在第一次加载后会进行缓存,然后每次刷新会使用缓存而不是去重新向服务器发送请求。如果不希望使用缓存可以设置no-cache。
以下属性在项目中没有应用过,可以写一个demo测试以下!
QQ浏览器私有
全屏模式
强制竖屏
强制横屏
应用模式
UC浏览器私有
全屏模式
强制竖屏
强制横屏
应用模式
其它
针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓
微软的老式浏览器
windows phone 点击无高光
解决方案:设置如下属性
这个不是 BUG,由于自动播放网页中的音频或视频,会给用户带来一些困扰或者不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放,必须由用户来触发才可以播放。
解决方法思路:先通过用户 touchstart 触碰,触发播放并暂停(音频开始加载,后面用 JS 再操作就没问题了)。
解决方案:
document.addEventListener('touchstart', function () {
document.getElementsByTagName('audio')[0].play();
document.getElementsByTagName('audio')[0].pause();
});
在父元素加transform: rotate(0deg)属性
.father {
transform: rotate(0deg)
}
给动画元素设置transform: translate3d(0, 0, 0);
.animation {
transform: translate3d(0, 0, 0);
}
原因:
设置opacity小于等于0.01时,就会出现这个问题
解决方案:
设置opacity大于0.01
.box {
opacity:0.011
}
原因:
globalThis为undefined的原因,globalThis的兼容性
解决方案:
给在入口的html文件将globalThis指向window
原因:
转换需要给图片设置允许跨域,但是在ios手机上允许跨域和给src赋值有顺序的区别,在chrome模拟没顺序问题
解决方案:
先给Image对象设置允许跨域,再给Image对象的src赋值
原因:
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,
};
});