請(qǐng)?jiān)斀庖苿?dòng)端點(diǎn)透,為什么會(huì)發(fā)生點(diǎn)透?描述發(fā)生的場(chǎng)景及解決方案
提到移動(dòng)端點(diǎn)透問(wèn)題,就不得不先提到移動(dòng)端的click事件300ms延遲問(wèn)題
一、移動(dòng)端click事件300ms延遲問(wèn)題
在移動(dòng)端執(zhí)行click事件時(shí),通常移動(dòng)端的瀏覽器會(huì)延遲300ms來(lái)觸發(fā)對(duì)應(yīng)的事件,這個(gè)問(wèn)題的原因是:為了判斷用戶是否是雙擊,因?yàn)樵谝苿?dòng)端瀏覽器剛開(kāi)始的時(shí)候,為了提升用戶體驗(yàn)感,開(kāi)發(fā)了雙擊縮放和雙擊滾動(dòng)等默認(rèn)行為,在之前的web開(kāi)發(fā)中,體驗(yàn)并不明顯,在當(dāng)前運(yùn)行速度和用戶體驗(yàn)至上的時(shí)代,這個(gè)問(wèn)題表現(xiàn)的特別嚴(yán)重。
移動(dòng)端click事件300ms延遲解決方案
- 添加meta標(biāo)簽,阻止用戶雙擊縮放,并限制視口寬度
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> - 設(shè)置CSS
touch-action
CSS屬性 touch-action 用于指定某個(gè)給定的區(qū)域是否允許用戶操作,以及如何響應(yīng)用戶操作(比如瀏覽器自帶的劃動(dòng)、縮放等)。* { touch-action: none; } -
fastclick.js
fastclick.js- github網(wǎng)址
移動(dòng)端事件觸發(fā)順序:在移動(dòng)端,手指點(diǎn)擊一個(gè)元素,會(huì)經(jīng)過(guò):touchstart=>touchmove=>touchend=>click。
fastclick.js的原理是:FastClick的實(shí)現(xiàn)原理是在檢測(cè)到touchend事件的時(shí)候,會(huì)通過(guò)DOM自定義事件立即觸發(fā)模擬一個(gè)click事件,并把瀏覽器在300ms之后真正的click事件阻止掉。
在原生js中可以如下使用:
在jquery或zpeto中可以如下使用:if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); } // 文章由 郝晨光 整理,未經(jīng)同意禁止轉(zhuǎn)載
在cli工具中(require或者import)$(function() { FastClick.attach(document.body); });const FastClick = require('fastclick'); // import FastClick from 'fastclick'; FastClick.attach(document.body, options);
二、移動(dòng)端點(diǎn)透問(wèn)題
點(diǎn)透問(wèn)題出現(xiàn)的場(chǎng)景
當(dāng)A/B兩個(gè)層上下z軸重疊,上層的A點(diǎn)擊后消失或移開(kāi)(這一點(diǎn)很重要),并且B元素本身有默認(rèn)click事件(如a標(biāo)簽)或綁定了click事件。在這種情況下,點(diǎn)擊A/B重疊的部分,就會(huì)出現(xiàn)點(diǎn)透的現(xiàn)象。
總結(jié)如下:
- A/B兩個(gè)層上下z軸重疊(上下重疊,A蓋著B)。
- 上層的A點(diǎn)擊后消失或移開(kāi)。(這一點(diǎn)很重要)
- B元素本身有默認(rèn)click事件(如a標(biāo)簽) 或 B綁定了click事件。
點(diǎn)透問(wèn)題的出現(xiàn)原因
點(diǎn)透問(wèn)題出現(xiàn)的原因就是因?yàn)槲覀兩线呎f(shuō)過(guò)的移動(dòng)端click事件300ms延遲問(wèn)題,當(dāng)點(diǎn)擊上層元素時(shí),先觸發(fā)touchstart事件,然后在300ms后會(huì)觸發(fā)click事件,而此時(shí)上層元素已經(jīng)消失,所以下邊的元素會(huì)觸發(fā)click事件,這就是點(diǎn)透
點(diǎn)透問(wèn)題的解決方案
fastclick.js
fastclick.js既然可以解決click300ms延遲,那必然可以解決點(diǎn)透問(wèn)題,使用方法如上文所述。對(duì)于B元素本身存在默認(rèn)click事件的情況,使用
touchend代替touchstart事件并阻止掉時(shí)A元素touchend的默認(rèn)行為preventDefault(),因?yàn)橛|發(fā)touchend需要200ms,從而阻止click事件的產(chǎn)生。使用一個(gè)(透明)遮罩層,屏蔽所有事件,然后400ms(對(duì)于IOS來(lái)說(shuō)是個(gè)理想值)后自動(dòng)隱藏
延遲一定的時(shí)間(300ms+)來(lái)處理事件
直接使用click事件,不考慮延遲問(wèn)題
下層避開(kāi)click事件,如a鏈接改為span等標(biāo)簽,使用js跳轉(zhuǎn)頁(yè)面
移動(dòng)端為什么會(huì)有一像素問(wèn)題?如何解決?
為什么會(huì)有一像素問(wèn)題?
因?yàn)樵谝苿?dòng)端,由于屏幕分辨率的不同,現(xiàn)在分為一倍屏、二倍屏、三倍屏。在不同的分辨率上,有可能一像素被渲然成二個(gè)像素點(diǎn)或者三個(gè)像素點(diǎn),所以在實(shí)際寫代碼的時(shí)候,我們寫的 border: 1px solid #000; 可能實(shí)際被渲然為 2px/3px;
一像素問(wèn)題的解決方案
-
先使用偽類元素實(shí)現(xiàn)邊框效果,然后通過(guò)媒體查詢來(lái)操控
transform: scale來(lái)適配不同分辨率.border-bottom{ position: relative; } .border-bottom::after { content: " "; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background-color: #e4e4e4; -webkit-transform-origin: left bottom; transform-origin: left bottom; } /* 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); } } -
使用border-image來(lái)代替border
.border-image-1px { border-width: 1px 0px; -webkit-border-image: url("border.png") 2 0 stretch; border-image: url("border.png") 2 0 stretch; } -
使用viewport +rem
設(shè)置meta標(biāo)簽
并在js中通過(guò)判斷當(dāng)前是一倍屏還是二倍屏、三倍屏,來(lái)動(dòng)態(tài)的設(shè)置meta標(biāo)簽的內(nèi)容<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />function rem() { document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; let viewport = document.querySelector("#WebViewport") 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') } } rem() window.onresize = rem; // 文章由 郝晨光 整理,未經(jīng)同意禁止轉(zhuǎn)載 -
border.css
通過(guò)項(xiàng)目中引入border.css來(lái)解決
你還知不知道其他移動(dòng)端的常見(jiàn)問(wèn)題?
-
html5調(diào)用安卓或者ios的撥號(hào)功能
html5提供了自動(dòng)調(diào)用撥號(hào)的標(biāo)簽,只要在a標(biāo)簽的href中添加tel:就可以了。<a href="tel:10086">點(diǎn)擊撥打10086</a> -
IOS設(shè)備鏈接、按鈕等點(diǎn)擊產(chǎn)生灰色背景
-webkit-tab-highlight-color:rgba(0,0,0,0); //去掉背景高亮 -webkit-tab-highlight-color: red; //設(shè)置背景高亮的顏色 ios設(shè)備微信瀏覽器或者Safari中fixed定位的部分會(huì)跟隨滑動(dòng)跳動(dòng)
在移動(dòng)端始終使用absloute來(lái)模擬fixed絕對(duì)定位,而不使用fixed-
移動(dòng)端HTML5 audio autoplay失效問(wèn)題
由于自動(dòng)播放網(wǎng)頁(yè)中的音頻或視頻會(huì)給用戶帶來(lái)困擾或不必要的流量消耗,所以蘋果系統(tǒng)和安卓系統(tǒng)通常都會(huì)禁止自動(dòng)播放和使用JS的觸發(fā)播放,必須由用戶來(lái)觸發(fā)才播放;解決方法思路:先通過(guò)用戶touchstart觸碰觸發(fā)播放并暫停(讓音頻開(kāi)始加載),后面用JS再操作就沒(méi)問(wèn)題了;解決代碼:document.addEventListener('touchstart', function () { document.getElementsByTagName('audio')[0].play(); document.getElementsByTagName('audio')[0].pause(); }); -
CSS動(dòng)畫頁(yè)面閃白,動(dòng)畫卡頓,圖片錯(cuò)亂的問(wèn)題
1.盡可能地使用合成屬性transform和opacity來(lái)設(shè)計(jì)CSS3動(dòng)畫,不使用position的left和top來(lái)定位;
2.開(kāi)啟硬件加速;-webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); //可以觸發(fā)硬件加速,從而讓瀏覽器在渲染動(dòng)畫時(shí)從CPU轉(zhuǎn)向GPU -
長(zhǎng)按頁(yè)面元素被選中
使用css屬性user-select-webkit-user-select:none; // webkit瀏覽器 -khtml-user-select:none; // 早期瀏覽器 -moz-user-select:none; // 火狐 -ms-user-select:none; // IE10 user-select:none; -
頂部狀態(tài)欄背景色
<meta name="apple-mobile-web-app-status-bar-style" content="black" />除非你先使用apple-mobile-web-app-capable指定全屏模式,否則這個(gè)meta標(biāo)簽不會(huì)起任何作用;
如果content設(shè)置為default,則狀態(tài)欄正常顯示;
如果設(shè)置為blank,則狀態(tài)欄會(huì)有一個(gè)黑色的背景;
如果設(shè)置為blank-translucent,則狀態(tài)欄顯示為黑色半透明;
如果設(shè)置為default或blank,則頁(yè)面顯示在狀態(tài)欄的下方,即狀態(tài)欄占據(jù)上方部分;頁(yè)面占據(jù)下方部分,二者沒(méi)有遮擋對(duì)方或被遮擋;
如果設(shè)置為blank-translucent,則頁(yè)面會(huì)充滿屏幕,其中頁(yè)面頂部會(huì)被狀態(tài)欄遮蓋住(會(huì)覆蓋頁(yè)面20px高度,而iphone4和itouch4的Retina屏幕為40px);
如果本文對(duì)您有幫助,可以看看本人的其他文章:
前端常見(jiàn)面試題(八)@郝晨光
前端常見(jiàn)面試題(七)@郝晨光
前端常見(jiàn)面試題(六)@郝晨光
本文 CSDN 地址: 前端常見(jiàn)面試題(九)@郝晨光