移动端如何进行适配
- 使用 viewprot 配合 vw/vh。
首先给 html 文件增加 viewport 配置
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
然后利用插件postcss-px-to-viewport
,根据设计稿的尺寸配置视口的宽高。然后该插件在构建过程中就会将 px 转成 vw。
- 使用 viewport 配合 rem;
rem 是以 html 元素的 font-size 为单位的尺寸;
首先给 html 文件增加 viewport 配置,将布局视口调整为设备的可视宽高
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
假设设计稿是按照 iphone6 来设计的,那么设计稿中采用的应该是750*1334px
的物理像素;
那么,我们可以设置 html 根元素的尺寸为font-size: 100px
;
为什么是 100px?定为 100px 的话,我们就是将 750 的设计稿分成了 7.5rem,1rem 为 100px;
所以,根元素的字体为 100px;
document.documentElement.style.fontSize = 750 / 7.5;
但是到了不同尺寸的手机中,根元素就不能为 100px 了,但是我们还是希望简单的使用 设计稿物理像素 / 100 = ?rem 的方式计算出元素的 rem。那么字体就需要根据不同的手机的逻辑像素(视口宽度)
来计算;
document.documentElement.style.fontSize = (screen.width / 750) * 100 + "px";
这样,在项目中就可以愉快的将所有设计稿尺寸除以 100 来算 rem 了
移动端 input 内的文字和同行文本在 android 中不对齐
<div class="wrap">
<input type="text" pattern="[0-9]*" />
<span>其他内容</span>
<div></div>
</div>
这个问题在 ios 中是不存在的,并且如果将 input 和同行的文本都设置高度和 line-height,虽然在 android 中会对齐,但是 ios 中 input 内的文字又会往下掉。。。所以,我使用了两套 css,ios 中不处理,android 中增加居中的一些样式
const isIPhone = new RegExp("\\biPhone\\b|\\biPod\\b", "i").test(
window.navigator.userAgent
);
移动端滚动穿透
当某个页面高度超过了屏幕并且可以滚动,且这个页面中有模态框。当模态框打开后,底下的页面还是可以滚动。可以使用一下的方法来解决
const fixScroll = (function () {
const oBody = document.getElementsByTagName("body")[0];
return function (visible) {
if (visible) {
oBody.style.position = "fixed";
oBody.style.overflow = "hidden";
} else {
oBody.style.position = "static";
oBody.style.overflow = "visible";
}
};
})();
// fixScroll(true) 在显示弹框的时候调用
// fixScroll(false) 在隐藏弹框的时候调用
H5 和 webview 回退刷新问题
项目是一个运行在 webview 中中的 h5 页面,在页面中需要跳转到第三方的页面,且回退后需要刷新页面。然后就遇到了 bfcache
什么是 bfcache
bfcache(back-forward cache),也可叫做“往返缓存”。是为了用户在使用浏览器的“返回”和“前进”按钮时,加快页面的转换速度。它实际上是将整个页面(数据、DOM、js)保存在了内存中。如果页面位于 bfcache 中,那么再次打开这个页面则不会触发 onload 事件
解决方案
JS 监听 pageshow 事件阻止页面进入 bfcache
window.addEventListener("pageshow", function (e) {
if (e.persisted) {
window.location.reload();
}
});
关于 ios 下通过 navigator.geolocation.getCurrentPosition 获取经纬度信息
在 ios 中,需要使用 https,才能调用 navigator.geolocation.getCurrentPosition
获取经纬度信息。
可以通过 iframe 的方式绕过 ios 的限制(但是无法绕过谷歌浏览器的限制)
var options = {
enableHighAccuracy: true,
maximumAge: 30000,
timeout: 12000,
};
window.showPosition = function (position) {
console.log(position.coords.longitude);
console.log(position.coords.latitude);
};
window.showError = function (error) {
switch (error.code) {
case error.PERMISSION_DENIED:
alert("用户不允许地理定位!");
break;
case error.POSITION_UNAVAILABLE:
alert("无法获取当前位置!");
break;
case error.TIMEOUT:
alert("操作超时!");
break;
case error.UNKNOWN_ERROR:
alert("未知错误!");
break;
}
};
window.locationCallback = function (err, position) {
if (err) {
showError(err);
return;
}
showPosition(position);
};
var str =
'<iframe src="javascript:(function(){ ' +
"window.navigator.geolocation.getCurrentPosition(" +
"function(position){parent && parent.locationCallback && parent.locationCallback(null,position);}, " +
"function(err){parent && parent.locationCallback && parent.locationCallback(err);}, " +
"{enableHighAccuracy : " +
options.enableHighAccuracy +
", maximumAge : " +
options.maximumAge +
", timeout :" +
options.timeout +
"})" +
';})()" style="display:none;"></iframe>';
var div = document.createElement("div");
div.innerHTML = str;
document.body.appendChild(div);