一、從布局說起移動端的整體布局一般來說可以分為上中下三個部分,分別為 header、main、foote" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運(yùn)營 > 移動端 Web 開發(fā)踩坑之旅

移動端 Web 開發(fā)踩坑之旅

時間:2022-07-27 23:30:01 | 來源:網(wǎng)站運(yùn)營

時間:2022-07-27 23:30:01 來源:網(wǎng)站運(yùn)營

前言

最近在一個移動端的 Web 項目中踩了很多的坑,感覺有必要把它們記錄下來,分享給即將踏入移動端 Web 開發(fā)大門的新人們。

一、從布局說起

移動端的整體布局一般來說可以分為上中下三個部分,分別為 header、main、footer,其中header、footer 是固定高度,分別固定在頁面頂部和頁面底部,而 main 是占據(jù)頁面其余位置,并且可以滾動。



(上圖是使用純 CSS 實現(xiàn),然后截圖,上傳到專欄有點(diǎn)失真,看官老爺們將就著看吧。)

頁面布局如下:

<body> <div class="header"></div> <div class="main"></div> <div class="footer"></div></body>根據(jù)頁面滾動的位置分為兩種布局,一種是滾動 body,另一種是固定 body 的高度為100%,在 main 中滾動。


第一種布局有個優(yōu)點(diǎn),就是頁面的地址欄會隨著 body 的滾動隱藏起來,并且 Android 設(shè)備中,滾動 body 會更加的流暢,如果項目中有類似需求可以考慮。

實現(xiàn)布局的方式如下:

body { overflow: auto;}.header,.footer { position: fixed; left: 0; right: 0; height: 44px;}.header { top: 0;}.footer { bottom: 0;}.main { height: 100%; padding: 44px 0;}第一種情況比較適合長列表頁面,整個頁面除了 header 和 footer 之外都需要滾動,但很多時候,我們只希望頁面的某個元素滾動,這個時候,就采取第二種布局方式。


這種頁面布局有三種相對簡單的實現(xiàn)方式:

  1. fixed 定位
  2. absolute 定位
  3. flex 定位


最容易想到的實現(xiàn)方式是 fixed 定位,實現(xiàn)方式如下:

html, body { height: 100%; overflow: hidden;}.header,.footer { position: fixed; left: 0; right: 0; height: 44px;}.header { top: 0;}.footer { bottom: 0;}.main { height: 100%; padding: 44px 0; box-sizing: border-box;}fixed 定位實現(xiàn)起來簡單,在大多數(shù)瀏覽器中也能正常顯示,但是 fixed 定位在移動端會有兼容性問題,后面會提到,所以不建議這種實現(xiàn)方式。



absolute 定位和 fixed 定位類似,只要把 header 的 footer 的 position 改為 absolute 就可以了。


細(xì)心的小伙伴可能發(fā)現(xiàn)了,這里的 main 沒有設(shè)置 overflow ,因為這里有一個坑,不管是absolute 定位還是 fixed 定位都一樣,為了方便描述,以下只說 fixed 定位(在 absolute 定位也一樣成立)。在PC端沒有問題,但是在移動端,如果 main 設(shè)置了 overflow 為 true,header 會被 main 遮住,對,沒有錯,雖然是 fixed 定位,但是在移動端,如果 fixed 定位節(jié)點(diǎn)后面緊接跟著的兄弟節(jié)點(diǎn)是可滾動的(也就是設(shè)置了 overflow 為 true ),那么 fixed 節(jié)點(diǎn)會被其后的兄弟節(jié)點(diǎn)遮住。


這個問題解決方式有很多,既然是 fixed 定位后面緊接著可滾動的兄弟節(jié)點(diǎn)才會有這個坑,只要讓他的條件有一個不成立就好了,有以下解決方案:


  1. 讓 fixed 定位節(jié)點(diǎn)后面不緊接著可滾動的節(jié)點(diǎn)
  2. 不讓 scroll 節(jié)點(diǎn)遮住 fixed 節(jié)點(diǎn)


第一種方方案有以下可選方法:

1. 把所有 fixed 節(jié)點(diǎn)放在 scroll 元素后面,即把 header 節(jié)點(diǎn)放在 main 節(jié)點(diǎn)后面

<body> <div class="main"></div> <div class="header"></div> <div class="footer"></div></body>但這樣顯然不太符合一般人的思維習(xí)慣,代碼可讀性降低。

2. 使 main 不可滾動,給 main 嵌套一層可滾動的子節(jié)點(diǎn)

<body> <div class="header"></div> <div class="main"> <div class="scroll-container"></div> </div> <div class="footer"></div></body><style> .main { overflow: hidden; } .scroll-container { height: 100%; overflow: auto; }</style>

第二種方案有以下可選方法:


1. 讓 scroll 節(jié)點(diǎn)不與 fixed 節(jié)點(diǎn)有重合

body { padding: 44px 0;}.main { padding: 0;}2. 給 fixed 節(jié)點(diǎn)設(shè)置 z-index

.header,.footer { z-index: 8888;}看到這里可能會有小伙伴覺得,一個簡單的布局,還要繞過這么多坑,難道沒有簡單的方式嗎,答案當(dāng)然是肯定的,那就是第三種實現(xiàn)方式,flex 布局。flex 定位在移動端兼容到了 iOS 7.1+,Android 4.4+,如果使用 autoprefixer 等工具還可以降級為舊版本的 flexbox ,可以兼容到 iOS 3.2 和 Android 2.1。而且用 flex 實現(xiàn)起來相對簡單,在各個瀏覽器里表現(xiàn)也相對一致。實現(xiàn)如下:

body { display: flex; flex-direction: column;}.main { flex: 1; overflow: auto; -webkit-overflow-scrolling: touch;}.header { height: 44px;}.footer { height: 44px;}

二、fixed 與 input

剛接觸移動端 Web 開發(fā)的小伙伴應(yīng)該都會聽前輩們說過,不要在有 input 標(biāo)簽的頁面使用 fixed 定位,因為這兩者在一起的時候,總是會有奇奇怪怪的問題。


在 iOS 上,當(dāng)點(diǎn)擊 input 標(biāo)簽獲取焦點(diǎn)喚起軟鍵盤的時候,fixed 定位會暫時失效,或者可以理解為變成了 absolute 定位,在含有滾動的頁面,fixed 定位的節(jié)點(diǎn)和其他節(jié)點(diǎn)一起滾動。


其實這個問題也很好解決,只要保證 fixed 定位的節(jié)點(diǎn)的父節(jié)點(diǎn)不可滾動,那么即使 fixed 定位失效,也不會和其他滾動節(jié)點(diǎn)一起滾動,影響界面。


但是除此之外,還有很多坑比較難以解決,例如 Android 軟鍵盤喚起后遮擋住 input 標(biāo)簽,用戶沒法看到自己輸入的字符串,iOS 則需要在輸入至少一個字符之后,才能將對應(yīng)的 input 標(biāo)簽滾動到合適的位置,所以為了避開這些難以解決的坑,在有表單輸入的頁面,盡量用absolute 或者 flex 替換 fixed。


三、input 的 compositionstart 和 compositionend 事件

在 Web 開發(fā)中,經(jīng)常要對表單元素的輸入進(jìn)行限制,比如說不允許輸入特殊字符,標(biāo)點(diǎn)。通常我們會監(jiān)聽 input 事件:

inputElement.addEventListener('input', function(event) { let regex = /[^1-9a-zA-Z]/g; event.target.value = event.target.value.replace(regex, ''); event.returnValue = false});這段代碼在 Android 上是沒有問題的,但是在 iOS 中,input 事件會截斷非直接輸入,什么是非直接輸入呢,在我們輸入漢字的時候,比如說「喜茶」,中間過程中會輸入拼音,每次輸入一個字母都會觸發(fā) input 事件,然而在沒有點(diǎn)選候選字或者點(diǎn)擊「選定」按鈕前,都屬于非直接輸入。



所以輸入「喜茶」兩個字,會觸發(fā)6次 input 事件,如果把每次 input 的 value 打印出來,結(jié)果如下:


這顯然不是我們想要的結(jié)果,我們希望在直接輸入之后才觸發(fā) input 事件,這就需要引出我要說的兩個事件—— compositionstart 和 compositionend。

compositionstart 事件在用戶開始進(jìn)行非直接輸入的時候觸發(fā),而在非直接輸入結(jié)束,也即用戶點(diǎn)選候選詞或者點(diǎn)擊「選定」按鈕之后,會觸發(fā) compositionend 事件。


var inputLock = false;function do(inputElement) { var regex = /[^1-9a-zA-Z]/g; inputElement.value = inputElement.value.replace(regex, '');}inputElement.addEventListener('compositionstart', function() { inputLock = true;});inputElement.addEventListener('compositionend', function(event) { inputLock = false; do(event.target);})inputElement.addEventListener('input', function(event) { if (!inputLock) { do(event.target); event.returnValue = false; }});
添加一個 inputLock 變量,當(dāng)用戶未完成直接輸入前,inputLock 為 true,不觸發(fā) input 事件中的邏輯,當(dāng)用戶完成有效輸入之后,inputLock 設(shè)置為 false,觸發(fā) input 事件的邏輯。這里需要注意的一點(diǎn)是,compositionend 事件是在 input 事件后觸發(fā)的,所以在 compositionend事件觸發(fā)時,也要調(diào)用 input 事件處理邏輯。


四、iOS 1px border 實現(xiàn)

iOS設(shè)備上,由于retina屏的原因,1px 的 border 會顯示成兩個物理像素,所以看起來會感覺很粗,這是一個移動端開發(fā)常見的問題。解決方案有很多,但都有自己的優(yōu)缺點(diǎn)。


0.5px border


從iOS 8開始,iOS 瀏覽器支持 0.5px 的 border,但是在 Android 上是不支持的,0.5px 會被認(rèn)為是 0px,所以這種方法,兼容性是很差的。


背景漸變


CSS3 有了漸變背景,可以通過漸變背景實現(xiàn) 1px 的 border,實現(xiàn)原理是設(shè)置 1px 的漸變背景,50% 有顏色,50% 是透明的。

@mixin commonStyle() { background-size: 100% 1px,1px 100% ,100% 1px, 1px 100%; background-repeat: no-repeat; background-position: top, right top, bottom, left top;}@mixin border($border-color) { @include commonStyle(); background-image:linear-gradient(180deg, $border-color, $border-color 50%, transparent 50%), linear-gradient(270deg, $border-color, $border-color 50%, transparent 50%), linear-gradient(0deg, $border-color, $border-color 50%, transparent 50%), linear-gradient(90deg, $border-color, $border-color 50%, transparent 50%);}
這種方法雖然可行,但是沒有辦法實現(xiàn)圓角。


偽類 + transform


這類方法的實現(xiàn)原理是用偽元素的 box-shadow 或 border 實現(xiàn) border,然后用 transform縮小到原來的一半。即使有圓角的需求也能很好的實現(xiàn)。

@mixin hairline-common($border-radius) { position: relative; z-index: 0; &:before { position: absolute; content: ''; border-radius: $border-radius; box-sizing: border-box; transform-origin: 0 0; }}@mixin hairline($direct: 'all', $border-color: #ccc, $border-radius: 0) { @include hairline-common($border-radius); &:before { transform: scale(.5); @if $direct == 'all' { top: 0; left: 0; width: 200%; height: 200%; box-shadow: 0 0 0 1px $border-color; z-index: -1; } @else if $direct == 'left' or $direct == 'right' { #{$direct}: 0; top: 0; width: 0; height: 200%; border-#{$direct}: 1px solid $border-color; } @else { #{$direct}: 0; left: 0; width: 200%; height: 0; border-#{$direct}: 1px solid $border-color; } }}

總結(jié)

以上的坑都是在項目里頻繁遇到的,每一個都給出了對應(yīng)的解決方式,但由于筆者也是初入坑移動 Web 開發(fā)的新人一枚,所以給出的方案未必是最合適的,做了點(diǎn)微小的工作,希望能為大家提供一點(diǎn)幫助,不足的地方也請大家多多指正。

關(guān)鍵詞:移動

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉