日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言

移動(dòng)端開發(fā)在前端里像神一樣地存在,不是說它多難而是說它坑位實(shí)在太多了,怎樣填都填不完。Android和IOS各顯神通,Android的系統(tǒng)版本和屏幕分辨率多得難以一招兼容,iOS的頑固標(biāo)準(zhǔn)和未知特性多得難以快速掌握。

三年半沉淀通過本文記錄下所遇到的坑位,或許有些坑位還未遇到,但本文記錄的40條坑位絕對(duì)能讓同學(xué)們少走很多彎路,特別是前端小白。為了減少?gòu)U話提高本文質(zhì)量,對(duì)以下內(nèi)容做一些約定。

  • 提及的安卓系統(tǒng)包括Android和基于Android開發(fā)的系統(tǒng)
  • 提及的蘋果系統(tǒng)包括iOS和iPadOS
  • 本文針對(duì)的開發(fā)場(chǎng)景是移動(dòng)端瀏覽器,因此大部分坑位的解決方案在桌面端瀏覽器里不一定有效
  • 解決方案若未提及適用系統(tǒng)就默認(rèn)在安卓系統(tǒng)和蘋果系統(tǒng)上都適用,若提及適用系統(tǒng)則會(huì)詳細(xì)說明
  • Webkit及其衍生內(nèi)核在移動(dòng)端瀏覽器市場(chǎng)占有率里達(dá)到驚人的97%,因此無需太過擔(dān)心css3、ES6和瀏覽器新特性的兼容性
  • 真正的開發(fā)環(huán)境都是基于webpack構(gòu)建,因此代碼演示都不會(huì)帶上CSS前綴,除非該屬性是Webkit獨(dú)有才會(huì)帶上-webkit-

每次填坑都是一次實(shí)踐過程,全部坑位的源碼都按語(yǔ)言方向記錄在筆者Github上,若有未記錄的坑位可提PR讓筆者合并,給個(gè)Star支持下咧!

本來想為每個(gè)坑位都截圖或錄制GIF作為演示,但考慮到目前掘金的Markdown編輯器操作圖片還存在缺陷就放棄了,每次上傳圖片都會(huì)花費(fèi)很多時(shí)間甚至上傳失敗(望掘金的產(chǎn)品小姐姐和程序小哥哥優(yōu)化喔)。若需演示只能自行復(fù)制代碼了。

html方向

調(diào)用系統(tǒng)功能

使用<a>能快速調(diào)用移動(dòng)設(shè)備的電話/短信/郵件三大通訊功能,使用<input>能快速調(diào)用移動(dòng)設(shè)備的的圖庫(kù)/文件。

這些功能方便了頁(yè)面與系統(tǒng)的交互,關(guān)鍵在于調(diào)用格式一定要準(zhǔn)確,否則會(huì)被移動(dòng)端瀏覽器忽略。

<!-- 撥打電話 -->
<a href="tel:10086">撥打電話給10086小姐姐</a>

<!-- 發(fā)送短信 -->
<a href="sms:10086">發(fā)送短信給10086小姐姐</a>

<!-- 發(fā)送郵件 -->
<a href="mailto:[email protected]">發(fā)送郵件給JowayYoung</a>

<!-- 選擇照片或拍攝照片 -->
<input type="file" accept="image/*">

<!-- 選擇視頻或拍攝視頻 -->
<input type="file" accept="video/*">

<!-- 多選文件 -->
<input type="file" multiple>
復(fù)制代碼

忽略自動(dòng)識(shí)別

有些移動(dòng)端瀏覽器會(huì)自動(dòng)將數(shù)字字母符號(hào)識(shí)別為電話/郵箱并將其渲染成上述調(diào)用系統(tǒng)功能里的<a>。雖然很方便卻有可能違背需求。

<!-- 忽略自動(dòng)識(shí)別電話 -->
<meta name="format-detection" content="telephone=no">

<!-- 忽略自動(dòng)識(shí)別郵箱 -->
<meta name="format-detection" content="email=no">

<!-- 忽略自動(dòng)識(shí)別電話和郵箱 -->
<meta name="format-detection" content="telephone=no, email=no">
復(fù)制代碼

彈出數(shù)字鍵盤

使用<input type="tel">彈起數(shù)字鍵盤會(huì)帶上#和*,適合輸入電話。推薦使用<input type="number" pattern="d*">彈起數(shù)字鍵盤,適合輸入驗(yàn)證碼等純數(shù)字格式。

<!-- 純數(shù)字帶#和* -->
<input type="tel">

<!-- 純數(shù)字 -->
<input type="number" pattern="d*">
復(fù)制代碼

喚醒原生應(yīng)用

通過location.href與原生應(yīng)用建立通訊渠道,這種頁(yè)面與客戶端的通訊方式稱為URL Scheme,其基本格式為scheme://[path][?query],筆者曾經(jīng)發(fā)表過《H5與App的通訊方式》講述URL Scheme的使用。

  • scheme:應(yīng)用標(biāo)識(shí),表示應(yīng)用在系統(tǒng)里的唯一標(biāo)識(shí)
  • path:應(yīng)用行為,表示應(yīng)用某個(gè)頁(yè)面或功能
  • query:應(yīng)用參數(shù),表示應(yīng)用頁(yè)面或應(yīng)用功能所需的條件參數(shù)

URL Scheme一般由前端與客戶端共同協(xié)商。喚醒原生應(yīng)用的前提是必須在移動(dòng)設(shè)備里安裝了該應(yīng)用,有些移動(dòng)端瀏覽器即使安裝了該應(yīng)用也無法喚醒原生應(yīng)用,因?yàn)樗J(rèn)為URL Scheme是一種潛在的危險(xiǎn)行為而禁用它,像Safari和微信瀏覽器。還好微信瀏覽器可開啟白名單讓URL Scheme有效。

若在頁(yè)面引用第三方原生應(yīng)用的URL Schema,可通過抓包第三方原生應(yīng)用獲取其URL。

<!-- 打開微信 -->
<a href="weixin://">打開微信</a>

<!-- 打開支付寶 -->
<a href="alipays://">打開支付寶</a>

<!-- 打開支付寶的掃一掃 -->
<a href="alipays://platformapi/startapp?saId=10000007">打開支付寶的掃一掃</a>

<!-- 打開支付寶的螞蟻森林 -->
<a href="alipays://platformapi/startapp?appId=60000002">打開支付寶的螞蟻森林</a>
復(fù)制代碼

禁止頁(yè)面縮放

在智能手機(jī)的普及下,很多網(wǎng)站都具備桌面端和移動(dòng)端兩種瀏覽版本,因此無需雙擊縮放查看頁(yè)面。禁止頁(yè)面縮放可保障移動(dòng)端瀏覽器能無遺漏地展現(xiàn)頁(yè)面所有布局。

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, minimum-scale=1, maximum-scale=1">
復(fù)制代碼

禁止頁(yè)面緩存

Cache-Control指定請(qǐng)求和響應(yīng)遵循的緩存機(jī)制,不想使用瀏覽器緩存就禁止唄!

<meta http-equiv="Cache-Control" content="no-cache">
復(fù)制代碼

禁止字母大寫

有時(shí)在輸入框里輸入文本會(huì)默認(rèn)開啟首字母大寫糾正,就是輸入首字母小寫會(huì)被自動(dòng)糾正成大寫,特么的煩。直接聲明autocapitalize=off關(guān)閉首字母大寫功能和autocorrect=off關(guān)閉糾正功能。

<input autocapitalize="off" autocorrect="off">
復(fù)制代碼

針對(duì)Safari配置

貼一些Safari較零散且少用的配置。

<!-- 設(shè)置Safari全屏,在iOS7+無效 -->
<meta name="apple-mobile-web-app-capable" content="yes">

<!-- 改變Safari狀態(tài)欄樣式,可選default/black/black-translucent,需在上述全屏模式下才有效 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black">

<!-- 添加頁(yè)面啟動(dòng)占位圖 -->
<link rel="apple-touch-startup-image" href="pig.jpg" media="(device-width: 375px)">

<!-- 保存網(wǎng)站到桌面時(shí)添加圖標(biāo) -->
<link rel="apple-touch-icon" sizes="76x76" href="pig.jpg">

<!-- 保存網(wǎng)站到桌面時(shí)添加圖標(biāo)且清除默認(rèn)光澤 -->
<link rel="apple-touch-icon-precomposed" href="pig.jpg">
復(fù)制代碼

針對(duì)其他瀏覽器配置

貼一些其他瀏覽器較零散且少用的配置,主要是常用的QQ瀏覽器、UC瀏覽器和360瀏覽器。從網(wǎng)易MTL的測(cè)試數(shù)據(jù)得知,新版的QQ瀏覽器和UC瀏覽器已不支持以下<meta>聲明了。

<!-- 強(qiáng)制QQ瀏覽器豎屏 -->
<meta name="x5-orientation" content="portrait">

<!-- 強(qiáng)制QQ瀏覽器全屏 -->
<meta name="x5-fullscreen" content="true">

<!-- 開啟QQ瀏覽器應(yīng)用模式 -->
<meta name="x5-page-mode" content="app">

<!-- 強(qiáng)制UC瀏覽器豎屏 -->
<meta name="screen-orientation" content="portrait">

<!-- 強(qiáng)制UC瀏覽器全屏 -->
<meta name="full-screen" content="yes">

<!-- 開啟UC瀏覽器應(yīng)用模式 -->
<meta name="browsermode" content="application">

<!-- 開啟360瀏覽器極速模式 -->
<meta name="renderer" content="webkit">
復(fù)制代碼

讓:active有效,讓:hover無效

有些元素的:active可能會(huì)無效,而元素的:hover在點(diǎn)擊后會(huì)一直處于點(diǎn)擊狀態(tài),需點(diǎn)擊其他位置才能解除點(diǎn)擊狀態(tài)。給<body>注冊(cè)一個(gè)空的touchstart事件可將兩種狀態(tài)反轉(zhuǎn)。

<body ontouchstart></body>
復(fù)制代碼

CSS方向

自動(dòng)適應(yīng)布局

針對(duì)移動(dòng)端,筆者通常會(huì)結(jié)合JS依據(jù)屏幕寬度與設(shè)計(jì)圖寬度的比例動(dòng)態(tài)聲明<html>的font-size,以rem為長(zhǎng)度單位聲明所有節(jié)點(diǎn)的幾何屬性,這樣就能做到大部分移動(dòng)設(shè)備的頁(yè)面兼容,兼容出入較大的地方再通過媒體查詢做特別處理。

筆者通常將rem布局比例設(shè)置成1rem=100px,即在設(shè)計(jì)圖上100px長(zhǎng)度在CSS代碼上使用1rem表示。

function AutoResponse(width = 750) {
    const target = document.documentElement;
    if (target.clientWidth >= 600) {
        target.style.fontSize = "80px";
    } else {
        target.style.fontSize = target.clientWidth / width * 100 + "px";
    }
}
AutoResponse();
window.addEventListener("resize", () => AutoResponse());
復(fù)制代碼

當(dāng)然還可依據(jù)屏幕寬度與設(shè)計(jì)圖寬度的比例使用calc()動(dòng)態(tài)聲明<html>的font-size,這樣就能節(jié)省上述代碼。不對(duì),是完全代替上述代碼。

html {
    font-size: calc(100vw / 7.5);
}
復(fù)制代碼

若以iPad Pro分辨率1024px為移動(dòng)端和桌面端的斷點(diǎn),還可結(jié)合媒體查詢做斷點(diǎn)處理。1024px以下使用rem布局,否則不使用rem布局。

@media screen and (max-width: 1024px) {
    html {
        font-size: calc(100vw / 7.5);
    }
}
復(fù)制代碼

自動(dòng)適應(yīng)背景

使用rem布局聲明一個(gè)元素背景,多數(shù)情況會(huì)將background-size聲明為cover。可能在設(shè)計(jì)圖對(duì)應(yīng)分辨率的移動(dòng)設(shè)備下,背景會(huì)完美貼合顯示,但換到其他分辨率的移動(dòng)設(shè)備下就會(huì)出現(xiàn)左右空出1px到npx的空隙。

此時(shí)將background-size聲明為100% 100%,跟隨width和height的變化而變化。反正width和height都是量好的實(shí)際尺寸。

.elem {
    width: 1rem;
    height: 1rem;
    background: url("pig.jpg") no-repeat center/100% 100%;
}
復(fù)制代碼

監(jiān)聽屏幕旋轉(zhuǎn)

你還在使用JS判斷橫屏豎屏調(diào)整樣式嗎?那就真的Out了。

/* 豎屏 */
@media all and (orientation: portrait) {
    /* 自定義樣式 */
}
/* 橫屏 */
@media all and (orientation: landscape) {
    /* 自定義樣式 */
}
復(fù)制代碼

支持彈性滾動(dòng)

在蘋果系統(tǒng)上非<body>元素的滾動(dòng)操作可能會(huì)存在卡頓,但安卓系統(tǒng)不會(huì)出現(xiàn)該情況。通過聲明overflow-scrolling:touch調(diào)用系統(tǒng)原生滾動(dòng)事件優(yōu)化彈性滾動(dòng),增加頁(yè)面滾動(dòng)的流暢度。

body {
    -webkit-overflow-scrolling: touch;
}
.elem {
    overflow: auto;
}
復(fù)制代碼

禁止?jié)L動(dòng)傳播

與桌面端瀏覽器不一樣,移動(dòng)端瀏覽器有一個(gè)奇怪行為。當(dāng)頁(yè)面包含多個(gè)滾動(dòng)區(qū)域時(shí),滾完一個(gè)區(qū)域后若還存在滾動(dòng)動(dòng)量則會(huì)將這些剩余動(dòng)量傳播到下一個(gè)滾動(dòng)區(qū)域,造成該區(qū)域也滾動(dòng)起來。這種行為稱為滾動(dòng)傳播

若不想產(chǎn)生這種奇怪行為可直接禁止。

.elem {
    overscroll-behavior: contain;
}
復(fù)制代碼

禁止屏幕抖動(dòng)

對(duì)于一些突然出現(xiàn)滾動(dòng)條的頁(yè)面,可能會(huì)產(chǎn)生左右抖動(dòng)的不良影響。在一個(gè)滾動(dòng)容器里,打開彈窗就隱藏滾動(dòng)條,關(guān)閉彈窗就顯示滾動(dòng)條,來回操作會(huì)讓屏幕抖動(dòng)起來。提前聲明滾動(dòng)容器的padding-right為滾動(dòng)條寬度,就能有效消除這個(gè)不良影響。

每個(gè)移動(dòng)端瀏覽器的滾動(dòng)條寬度都有可能不一致,甚至不一定占位置,通過以下方式能間接計(jì)算出滾動(dòng)條的寬度。100vw為視窗寬度,100%為滾動(dòng)容器內(nèi)容寬度,相減就是滾動(dòng)條寬度,妥妥的動(dòng)態(tài)計(jì)算。

body {
    padding-right: calc(100vw - 100%);
}
復(fù)制代碼

禁止長(zhǎng)按操作

有時(shí)不想用戶長(zhǎng)按元素呼出菜單進(jìn)行點(diǎn)鏈接、打電話、發(fā)郵件、保存圖片或掃描二維碼等操作,聲明touch-callout:none禁止用戶長(zhǎng)按操作。

有時(shí)不想用戶復(fù)制粘貼盜文案,聲明user-select:none禁止用戶長(zhǎng)按操作和選擇復(fù)制。

* {
    /* pointer-events: none; */ /* 微信瀏覽器還需附加該屬性才有效 */
    user-select: none; /* 禁止長(zhǎng)按選擇文字 */
    -webkit-touch-callout: none;
}
復(fù)制代碼

但聲明user-select:none會(huì)讓<input>和<textarea>無法輸入文本,可對(duì)其聲明user-select:auto排除在外。

input,
textarea {
    user-select: auto;
}
復(fù)制代碼

禁止字體調(diào)整

旋轉(zhuǎn)屏幕可能會(huì)改變字體大小,聲明text-size-adjust:100%讓字體大小保持不變。

* {
    text-size-adjust: 100%;
}
復(fù)制代碼

禁止高亮顯示

觸摸元素會(huì)出現(xiàn)半透明灰色遮罩,不想要!

* {
    -webkit-tap-highlight-color: transparent;
}
復(fù)制代碼

禁止動(dòng)畫閃屏

在移動(dòng)設(shè)備上添加動(dòng)畫,多數(shù)情況會(huì)出現(xiàn)閃屏,給動(dòng)畫元素的父元素構(gòu)造一個(gè)3D環(huán)境就能讓動(dòng)畫穩(wěn)定運(yùn)行了。

.elem {
    perspective: 1000;
    backface-visibility: hidden;
    transform-style: preserve-3d;
}
復(fù)制代碼

美化表單外觀

表單元素樣式太丑希望自定義,appearance:none來幫你。

button,
input,
select,
textarea {
    appearance: none;
    /* 自定義樣式 */
}
復(fù)制代碼

美化滾動(dòng)占位

滾動(dòng)條樣式太丑希望自定義,::-webkit-scrollbar-*來幫你。記住以下三個(gè)關(guān)鍵詞就能隨機(jī)應(yīng)變了。

  • ::-webkit-scrollbar:滾動(dòng)條整體部分
  • ::-webkit-scrollbar-track:滾動(dòng)條軌道部分
  • ::-webkit-scrollbar-thumb:滾動(dòng)條滑塊部分
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
    background-color: transparent;
}
::-webkit-scrollbar-track {
    background-color: transparent;
}
::-webkit-scrollbar-thumb {
    border-radius: 3px;
    background-image: linear-gradient(135deg, #09f, #3c9);
}
復(fù)制代碼

美化輸入占位

輸入框占位文本太丑,
::-webkit-input-placeholder來幫你。

input::-webkit-input-placeholder {
    color: #66f;
}
復(fù)制代碼

對(duì)齊輸入占位

有強(qiáng)迫癥的同學(xué)總會(huì)覺得輸入框文本位置整體偏上,感覺未居中心里就癢癢的。桌面端瀏覽器里聲明line-height等于height就能解決,但移動(dòng)端瀏覽器里還是未能解決,需將line-height聲明為normal才行。

input {
    line-height: normal;
}
復(fù)制代碼

對(duì)齊下拉選項(xiàng)

下拉框選項(xiàng)默認(rèn)向左對(duì)齊,是時(shí)候改改向右對(duì)齊了。

select option {
    direction: rtl;
}
復(fù)制代碼

修復(fù)點(diǎn)擊無效

在蘋果系統(tǒng)上有些情況下非可點(diǎn)擊元素監(jiān)聽click事件可能會(huì)無效,針對(duì)該情況只需對(duì)不觸發(fā)click事件的元素聲明cursor:pointer就能解決。

.elem {
    cursor: pointer;
}
復(fù)制代碼

識(shí)別文本換行

多數(shù)情況會(huì)使用JS換行文本,那就真的Out了。若接口返回字段包含n或<br>,千萬(wàn)別替換掉,可聲明white-space:pre-line交由瀏覽器做斷行處理。

* {
    white-space: pre-line;
}
復(fù)制代碼

開啟硬件加速

想動(dòng)畫更流暢嗎,開啟GPU硬件加速唄!

.elem {
    transform: translate3d(0, 0, 0);
    /* transform: translateZ(0); */
}
復(fù)制代碼

描繪像素邊框

萬(wàn)年話題,如何描繪一像素邊框?

.elem {
    position: relative;
    width: 200px;
    height: 80px;
    &::after {
        position: absolute;
        left: 0;
        top: 0;
        border: 1px solid #f66;
        width: 200%;
        height: 200%;
        content: "";
        transform: scale(.5);
        transform-origin: left top;
    }
}
復(fù)制代碼

控制溢出文本

萬(wàn)年話題,如何控制文本做單行溢出和多行溢出?

.elem {
    width: 400px;
    line-height: 30px;
    font-size: 20px;
    &.sl-ellipsis {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    &.ml-ellipsis {
        display: -webkit-box;
        overflow: hidden;
        text-overflow: ellipsis;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
    }
}
復(fù)制代碼

JS方向

禁止點(diǎn)擊穿透

移動(dòng)端瀏覽器里點(diǎn)擊操作會(huì)存在300ms延遲,往往會(huì)造成點(diǎn)擊延遲甚至點(diǎn)擊無效,這個(gè)是眾所周知的事情。

2007年蘋果發(fā)布首款iphone搭載的Safari為了將桌面端網(wǎng)站能較好地展示在移動(dòng)端瀏覽器上而使用了雙擊縮放。該方案就是上述300ms延遲的主要原因,當(dāng)用戶執(zhí)行第一次單擊后會(huì)預(yù)留300ms檢測(cè)用戶是否繼續(xù)執(zhí)行單擊,若是則執(zhí)行縮放操作,若否則執(zhí)行點(diǎn)擊操作。鑒于該方案的成功,其他移動(dòng)端瀏覽器也復(fù)制了該方案,現(xiàn)在幾乎所有移動(dòng)端瀏覽器都配備該功能。而該方案引發(fā)的點(diǎn)擊延遲被稱為點(diǎn)擊穿透

在前端領(lǐng)域里最早解決點(diǎn)擊穿透是jQuery時(shí)代的zepto,估計(jì)現(xiàn)在大部分同學(xué)都未使用過zepto,其實(shí)它就是移動(dòng)端版本的jquery。zepto封裝tap事件能有效地解決點(diǎn)擊穿透,通過監(jiān)聽document上的touch事件完成tap事件的模擬,并將tap事件冒泡到document上觸發(fā)。

在移動(dòng)端瀏覽器上不使用click事件而使用touch事件是因?yàn)閏lick事件有著明顯的延遲,后續(xù)又出現(xiàn)fastclick。該解決方案監(jiān)聽用戶是否做了雙擊操作,可正常使用click事件,而點(diǎn)擊穿透就交給fastclick自動(dòng)判斷。更多fastclick原理可自行百度,在此不作過多介紹。

fastclick有現(xiàn)成的NPM包,可直接安裝到項(xiàng)目里。引入fastclick可使用click事件代替tap事件,接入方式極其簡(jiǎn)單。

import Fastclick from "fastclick";

FastClick.attach(document.body);
復(fù)制代碼

禁止滑動(dòng)穿透

移動(dòng)端瀏覽器里出現(xiàn)彈窗時(shí),若在屏幕上滑動(dòng)能觸發(fā)彈窗底下的內(nèi)容跟著滾動(dòng),這個(gè)是眾所周知的事情。

首先明確解決滑動(dòng)穿透需保持哪些交互行為,那就是除了彈窗內(nèi)容能點(diǎn)擊或滾動(dòng),其他內(nèi)容都不能點(diǎn)擊或滾動(dòng)。目前很多解決方案都無法做到這一點(diǎn),全部解決方案都能禁止<body>的滾動(dòng)行為卻引發(fā)其他問題。

  • 彈窗打開后內(nèi)部?jī)?nèi)容無法滾動(dòng)
  • 彈窗關(guān)閉后頁(yè)面滾動(dòng)位置丟失
  • Webview能上下滑動(dòng)露出底色

當(dāng)打開彈窗時(shí)給<body>聲明position:fixed;left:0;width:100%并動(dòng)態(tài)聲明top。聲明position:fixed會(huì)導(dǎo)致<body>滾動(dòng)條消失,此時(shí)會(huì)發(fā)現(xiàn)雖然無滑動(dòng)穿透,但頁(yè)面滾動(dòng)位置早已丟失。通過scrollingElement獲取頁(yè)面當(dāng)前滾動(dòng)條偏移量并將其取負(fù)值且賦值給top,那么在視覺上就無任何變化。當(dāng)關(guān)閉彈窗時(shí)移除position:fixed;left:0;width:100%和動(dòng)態(tài)top。

scrollingElement可兼容地獲取scrollTop和scrollHeight等屬性,在移動(dòng)端瀏覽器里屢試不爽。
document.scrollingElement.scrollHeight可完美代替曾經(jīng)的
document.documentElement.scrollHeight ||
document.body.scrollHeight,一眼看上去就是代碼減少了。

該解決方案在視覺上無任何變化,完爆其他解決方案,其實(shí)就是一種反向思維和障眼法。該解決方案完美解決固定彈窗和滾動(dòng)彈窗對(duì)<body>全局滾動(dòng)的影響,當(dāng)然也可用于局部滾動(dòng)容器里,因此很值得推廣。

body.static {
    position: fixed;
    left: 0;
    width: 100%;
}
復(fù)制代碼
const body = document.body;
const openBtn = document.getElementById("open-btn");
const closeBtn = document.getElementById("close-btn");
openBtn.addEventListener("click", e => {
    e.stopPropagation();
    const scrollTop = document.scrollingElement.scrollTop;
    body.classList.add("static");
    body.style.top = `-${scrollTop}px`;
});
closeBtn.addEventListener("click", e => {
    e.stopPropagation();
    body.classList.remove("static");
    body.style.top = "";
});
復(fù)制代碼

支持往返刷新

點(diǎn)擊移動(dòng)端瀏覽器的前進(jìn)按鈕或后退按鈕,有時(shí)不會(huì)自動(dòng)執(zhí)行舊頁(yè)面的JS代碼,這與往返緩存有關(guān)。這種情況在Safari上特別明顯,簡(jiǎn)單概括就是往返頁(yè)面無法刷新。

往返緩存指瀏覽器為了在頁(yè)面間執(zhí)行前進(jìn)后退操作時(shí)能擁有更流暢體驗(yàn)的一種策略,以下簡(jiǎn)稱BFCache。該策略具體表現(xiàn)為:當(dāng)用戶前往新頁(yè)面前將舊頁(yè)面的DOM狀態(tài)保存在BFCache里,當(dāng)用戶返回舊頁(yè)面前將舊頁(yè)面的DOM狀態(tài)從BFCache里取出并加載。大部分移動(dòng)端瀏覽器都會(huì)部署B(yǎng)FCache,可大大節(jié)省接口請(qǐng)求的時(shí)間和帶寬。

了解什么是BFCache再對(duì)癥下藥,解決方案就在window.onunload上做文章。

// 在新頁(yè)面監(jiān)聽頁(yè)面銷毀事件
window.addEventListener("onunload", () => {
    // 執(zhí)行舊頁(yè)面代碼
});
復(fù)制代碼

若在Vue SPA上使用keep-alive也不能讓頁(yè)面刷新,可將接口請(qǐng)求放到beforeRouteEnter()里。

當(dāng)然還有另一種解決方案。pageshow事件在每次頁(yè)面加載時(shí)都會(huì)觸發(fā),無論是首次加載還是再次加載都會(huì)觸發(fā),這就是它與load事件的區(qū)別。pageshow事件暴露的persisted可判斷頁(yè)面是否從BFCache里取出。

window.addEventListener("pageshow", e => e.persisted && location.reload());
復(fù)制代碼

若瀏覽器不使用<meta http-equiv="Cache-Control" content="no-cache">禁用緩存,該解決方案還是很值得一用。

解析有效日期

在蘋果系統(tǒng)上解析YYYY-MM-DD HH:mm:ss這種日期格式會(huì)報(bào)錯(cuò)Invalid Date,但在安卓系統(tǒng)上解析這種日期格式完全無問題。

new Date("2019-03-31 21:30:00"); // Invalid Date
復(fù)制代碼

查看Safari相關(guān)開發(fā)手冊(cè)發(fā)現(xiàn)可用YYYY/MM/DD HH:mm:ss這種日期格式,簡(jiǎn)單概括就是年月日必須使用/銜接而不能使用-銜接。當(dāng)然安卓系統(tǒng)也支持該格式,然而接口返回字段的日期格式通常是YYYY-MM-DD HH:mm:ss,那么需替換其中的-為/。

const date = "2019-03-31 21:30:00";
new Date(date.replace(/-/g, "/"));
復(fù)制代碼

修復(fù)高度坍塌

當(dāng)頁(yè)面同時(shí)出現(xiàn)以下三個(gè)條件時(shí),鍵盤占位會(huì)把頁(yè)面高度壓縮一部分。當(dāng)輸入完成鍵盤占位消失后,頁(yè)面高度有可能回不到原來高度,產(chǎn)生坍塌導(dǎo)致Webview底色露臉,簡(jiǎn)單概括就是輸入框失焦后頁(yè)面未回彈。

  • 頁(yè)面高度過小
  • 輸入框在頁(yè)面底部或視窗中下方
  • 輸入框聚焦輸入文本

只要保持前后滾動(dòng)條偏移量一致就不會(huì)出現(xiàn)上述問題。在輸入框聚焦時(shí)獲取頁(yè)面當(dāng)前滾動(dòng)條偏移量,在輸入框失焦時(shí)賦值頁(yè)面之前獲取的滾動(dòng)條偏移量,這樣就能間接還原頁(yè)面滾動(dòng)條偏移量解決頁(yè)面高度坍塌。

const input = document.getElementById("input");
let scrollTop = 0;
input.addEventListener("focus", () => {
    scrollTop = document.scrollingElement.scrollTop;
});
input.addEventListener("blur", () => {
    document.scrollingElement.scrollTo(0, scrollTop);
});
復(fù)制代碼

修復(fù)輸入監(jiān)聽

在蘋果系統(tǒng)上的輸入框輸入文本,keyup/keydown/keypress事件可能會(huì)無效。當(dāng)輸入框監(jiān)聽keyup事件時(shí),逐個(gè)輸入英文和數(shù)字會(huì)有效,但逐個(gè)輸入中文不會(huì)有效,需按回車鍵才會(huì)有效。

此時(shí)可用input事件代替輸入框的keyup/keydown/keypress事件。

簡(jiǎn)化回到頂部

曾幾何時(shí)編寫一個(gè)返回頂部函數(shù)麻煩得要死,需scrollTop、定時(shí)器和條件判斷三者配合才能完成。其實(shí)DOM對(duì)象里隱藏了一個(gè)很好用的函數(shù)可完成上述功能,一行核心代碼就能搞定。

該函數(shù)就是scrollIntoView,它會(huì)滾動(dòng)目標(biāo)元素的父容器使之對(duì)用戶可見,簡(jiǎn)單概括就是相對(duì)視窗讓容器滾動(dòng)到目標(biāo)元素位置。它有三個(gè)可選參數(shù)能讓scrollIntoView滾動(dòng)起來更優(yōu)雅。

  • behavior:動(dòng)畫過渡效果,默認(rèn)auto無,可選smooth平滑
  • inline:水平方向?qū)R方式,默認(rèn)nearest就近對(duì)齊,可選start頂部對(duì)齊、center中間對(duì)齊和end底部對(duì)齊
  • block:垂直方向?qū)R方式,默認(rèn)start頂部對(duì)齊,可選center中間對(duì)齊、end底部對(duì)齊和nearest就近對(duì)齊
const gotopBtn = document.getElementById("gotop-btn");
openBtn.addEventListener("click", () => document.body.scrollIntoView({ behavior: "smooth" }));
復(fù)制代碼

當(dāng)然還可滾動(dòng)到目標(biāo)元素位置,只需將document.body修改成目標(biāo)元素的DOM對(duì)象。一行核心代碼就能搞掂的事情為何還編寫那么多代碼去完成,不累嗎?

簡(jiǎn)化懶性加載

與上述簡(jiǎn)化回到頂部一樣,編寫一個(gè)懶性加載函數(shù)也同樣需scrollTop、定時(shí)器和條件判斷三者配合才能完成。其實(shí)DOM對(duì)象里隱藏了一個(gè)很好用的函數(shù)可完成上述功能,該函數(shù)無需監(jiān)聽容器的scroll事件,通過瀏覽器自身機(jī)制完成滾動(dòng)監(jiān)聽。

該函數(shù)就是IntersectionObserver,它提供一種異步觀察目標(biāo)元素及其祖先元素或頂級(jí)文檔視窗交叉狀態(tài)的方法。詳情可參照MDN文檔,在此不作過多介紹。

懶性加載的第一種使用場(chǎng)景:圖片懶加載。只需確認(rèn)圖片進(jìn)入可視區(qū)域就賦值加載圖片,賦值完成還需對(duì)圖片停止監(jiān)聽。

<img data-src="pig.jpg">
<!-- 很多<img> -->
復(fù)制代碼
const imgs = document.querySelectorAll("img.lazyload");
const observer = new IntersectionObserver(nodes => {
    nodes.forEach(v => {
        if (v.isIntersecting) { // 判斷是否進(jìn)入可視區(qū)域
            v.target.src = v.target.dataset.src; // 賦值加載圖片
            observer.unobserve(v.target); // 停止監(jiān)聽已加載的圖片
        }
    });
});
imgs.forEach(v => observer.observe(v));
復(fù)制代碼

懶性加載的第二種使用場(chǎng)景:下拉加載。在列表最底部部署一個(gè)占位元素且該元素?zé)o任何高度或?qū)嶓w外觀,只需確認(rèn)占位元素進(jìn)入可視區(qū)域就請(qǐng)求接口加載數(shù)據(jù)。

<ul>
    <li></li>
    <!-- 很多<li> -->
</ul>
<!-- 也可將#bottom以<li>的形式插入到<ul>內(nèi)部的最后位置 -->
<div id="bottom"></div>
復(fù)制代碼
const bottom = document.getElementById("bottom");
const observer = new IntersectionObserver(nodes => {
    const tgt = nodes[0]; // 反正只有一個(gè)
    if (tgt.isIntersecting) {
        console.log("已到底部,請(qǐng)求接口");
        // 執(zhí)行接口請(qǐng)求代碼
    }
})
observer.observe(bottom);
復(fù)制代碼

優(yōu)化掃碼識(shí)別

通常移動(dòng)端瀏覽器都會(huì)配備長(zhǎng)按二維碼圖片識(shí)別鏈接的功能,但長(zhǎng)按二維碼可能無法識(shí)別或錯(cuò)誤識(shí)別。二維碼表面看上去是一張圖片,可二維碼生成方式卻五花八門,二維碼生成方式有以下三種。

  • 使用<img>渲染
  • 使用<svg>渲染
  • 使用<canvas>渲染

從網(wǎng)易MTL的測(cè)試數(shù)據(jù)得知,大部分移動(dòng)端瀏覽器只能識(shí)別<img>渲染的二維碼,為了讓全部移動(dòng)端瀏覽器都能識(shí)別二維碼,那只能使用<img>渲染二維碼了。若使用SVG和Canvas的方式生成二維碼,那就想方設(shè)法把二維碼數(shù)據(jù)轉(zhuǎn)換成Base64再賦值到<img>的src上。

一個(gè)頁(yè)面可能存在多個(gè)二維碼,若長(zhǎng)按二維碼只能識(shí)別最后一個(gè),那只能控制每個(gè)頁(yè)面只存在一個(gè)二維碼。

自動(dòng)播放媒體

常見媒體元素包括音頻<audio>和視頻<video>,為了讓用戶得到更好的媒體播放體驗(yàn)與不盲目浪費(fèi)用戶流量,大部分移動(dòng)端瀏覽器都明確規(guī)定不能自動(dòng)播放媒體或默認(rèn)屏蔽autoplay。為了能讓媒體在頁(yè)面加載完成后自動(dòng)播放,只能顯式聲明播放。

const audio = document.getElementById("audio");
const video = document.getElementById("video");
audio.play();
video.play();
復(fù)制代碼

對(duì)于像微信瀏覽器這樣的內(nèi)置瀏覽器,還需監(jiān)聽其應(yīng)用SDK加載完成才能觸發(fā)上述代碼,以保障WebView正常渲染。其他內(nèi)置瀏覽器同理,在此不作過多介紹。

document.addEventListener("WeixinJSBridgeReady", () => {
    // 執(zhí)行上述媒體自動(dòng)播放代碼
});
復(fù)制代碼

在蘋果系統(tǒng)上明確規(guī)定用戶交互操作開始后才能播放媒體,未得到用戶響應(yīng)會(huì)被Safari自動(dòng)攔截,因此需監(jiān)聽用戶首次觸摸操作并觸發(fā)媒體自動(dòng)播放,而該監(jiān)聽僅此一次。

document.body.addEventListener("touchstart", () => {
    // 執(zhí)行上述媒體自動(dòng)播放代碼
}, { once: true });


作者:JowayYoung
鏈接:
https://juejin.cn/post/6921886428158754829
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

分享到:
標(biāo)簽:H5
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定