筆者最近一直在開發京東app嵌入的h5項目和微信小程序商城項目,在此期間遇到不少坑。這篇文章主要是針對 h5| Hybrid | 微信小程序 三個方向來說述我遇到的坑,以及詳細講解我是如何解決問題的。css
一直以來,移動端適配就是一個使人頭疼的問題。若是想要吃透移動端,還須要很多的實踐經驗,有的時候在pc
端調試沒有問題,可是在m端就會出現問題。如下這16個問題是我在實際工做中遇到的,親自奉上給你們。但願你們收藏一波,以備不時之需。html
喜歡筆者的能夠「點贊 + 收藏 」 一波,持續更新前端硬核文章。前端
如下是京東嵌入h5,h5落地頁,遇到的問題。我用一個思惟導圖表示出來。vue
在開發京東app,Hybrid h5
業務頁面的時候,遇到一個很是棘手的問題,由於這個頁面相似京東app商品詳情頁面的動畫效果。 動畫效果以下所示。安卓手機正常,可是ios手機出現,滑塊抖動問題,圖片會出現閃動的效果。這個問題困擾了好久,網上搜索了大量的解決方案,都沒有實際解決問題,本身也嘗試了幾種方法,也沒有成功,當時很奔潰😭😭😭,最後仍是靈光一現,想到了一個巧妙的解決方案😂。react
整個流程就是,當視圖容器向上滑動的時候,商品卡片容器須要緩慢移動,首先須要將商品卡片須要脫離標準流,設置定位position:fixed
固定定位。而後控制top
值來控制滑塊的緩慢移動。可是在容器向上滑動的過程當中,滑塊會出現抖動
,閃動
的效果。android
🤔分析這個緣由,應該是ios
對position
表現不友好的緣由,這種相似的緣由在小程序裏也很常見。ios
① 給頂級元素設置height:100%
( 並無奏效 ) 。web
② 增長 transform: translate(0)
屬性 ( 並無奏效 )算法
③ 改變佈局由fixed
定位,改爲absolute
定位,滾動條基於自身。( 可以從根本上解決偶爾跳屏的問題,可是隨之而來的就是ios
滾動條問題,基於document
纔能有效觸發,遂放棄此方案)canvas
④ 不改變佈局的狀況下,由fixed
定位,改爲absolute
定位,滾動條基於document
,定位值徹底取決於數據驅動。(可以從根本上解決偶爾跳屏的問題,可是隨之而來的就是要不斷改變自身的top值 ,致使更新會慢的狀況 ,用戶體驗很差,流暢度欠佳,遂放棄此方案 )
⑤ -webkit-overflow-scroll:touch
解決滑動無慣性( 並無奏效 )
⑥ background-attachment:fixed
( 並無奏效 )
試了很久,終於想到了一個解決方法。繼續使用 fixed
定位,由於咱們這裏須要經過定位,抖動不是單純fixed
定位的緣由。和頻繁改變top
值也有很大關係。放棄改變top
值 ,運用transform: translateY
來使視圖上下移動。
<view class="scroll_box" style={{ transform:`translateY(${ top }px)` }} >
<!-- 不少東西 -->
</view>
複製代碼
.scroll_box{
position:fixed;
}
複製代碼
當咱們指望用 border-radius:50%;
來繪製圓點的時候。若是圓比較大可能不是很明顯,可是若是圓比較小的時候,會出現明顯的不圓,圓被拉伸的狀況。
大體效果以下所示。
🤔分析緣由, 在移動端一般會適配不一樣的手機,因此使用rem
佈局,,rem
在換算爲px
時,會是一個帶小數點的值,安卓對小於1px
的作了處理(不一樣瀏覽器對小於1px
的處理方式不一樣,有的採用四捨五入,有的大於某個值展現1px
不然就捨去),從而致使圓角不圓;在ios
下就沒有這個問題。
咱們先把已知視圖寬高變成2倍 ,而後用 transform: scale(.5)
讓視圖縮小50% ,就能夠在 android
獲得很圓的效果。親測這個方法很是奏效,造成的圓很是的圓。
咱們舉個例子🌰:
<div class="round" ></div>
複製代碼
沒有作兼容以前的樣式,
.round{
border-radius:50%;
width:10px;
heigth:10px;
}
複製代碼
改爲
.round{
border-radius:50%;
width:20px;
heigth:20px;
transform: scale(.5);
}
複製代碼
這裏用的taro-h5
, px
會被自動轉化成rem
。
有的時候咱們在給元素設置高度很是小的時候也會出現這個問題。
<view class='box' />
複製代碼
.box{
width:100px;
height:1px;
}
複製代碼
由於咱們高度設置爲height:1px
,當taro
給轉換成rem
的時候,也會出現四捨五入的狀況,結果將1px
弄沒了,變成了0px
,因而乎就形成了1px
元素沒法顯示的bug
,解決方案和上述的原理同樣。將高度變成原來的2倍,再經過transform: scaleY(.5);
y方向變爲原來的二分之一。
.box{
width:100px;
height:2px;
transform: scaleY(.5);
}
複製代碼
這個問題在ios
環境下,仍是很容易發生的。當視圖容器的最後一個元素設置 margin-bottom
,指望距離整個容器視圖有一個距離的時候,發如今安卓手機正常,可是在ios
下,會出現margin-bottom
無效的狀況。
這個的解決方案也很是很是的簡單,將margin-bottom
改爲padding-bottom
就能根本的解決問題。
例子🌰:
<div class="box" ></div>
複製代碼
.box{
margin-bottom: 148px;
}
複製代碼
改爲
.box{
padding-bottom: 148px;
}
複製代碼
手指按住屏幕下拉,屏幕頂部會多出一塊空白區域。手指按住屏幕上拉,底部多出一塊空白區域。空白區域的顏色,在不一樣app
平臺打開,顏色會有差異,嵌入京東app h5中的空白背景色爲白色,可是在微信中爲灰色。
🤔分析緣由: 在 iOS
中,手指按住屏幕上下拖動,會觸發 touchmove
事件。這個事件觸發的對象是整個 webview
容器,容器天然會被拖動,剩下的部分會成空白。
效果以下:
好比對於京東app這種白色背景,若是咱們background
也是白色的,徹底能夠用整個頂端容器,定位填充整個容器來解決這個問題。這樣視圖不會跟隨上拉下滑而移動。若是空白顏色和背景顏色一致,視覺上就會抵消滑動效果。根本上解決出現空白的問題。
一言不合上代碼😜。
<div id="root" >
<!-- 此處省略不少內容 -->
</div>
複製代碼
#root{
position: fixed;
left:0;
top:0;
bottom: 0;
right: 0;
}
複製代碼
這種方法比較靠譜,俗話說解鈴還須繫鈴人
,這個問題根本緣由是 touchmove
引發的,那麼從根本上解決問題,仍是要從touchmove
這個事件入手。咱們須要監聽移動端document
的 touchmove
而後經過 preventDefault
方法,阻止同一觸點上全部默認行爲,好比滾動事件。這裏要注意的是何時,不讓滑動,何時讓滑動。
<div ref="root" ></div>
複製代碼
const box = this.$refs.root
box.addEventListener('touchmove',function(e){
/* 讓視圖容器正常滾動 */
e._isScroller = true
})
/* 禁止上滑,下滑 */
document.body.addEventListener('touchmove', function (e) {
if (e._isScroller) return
/* 阻止默認事件 */
e.preventDefault()
}, {
passive: false
})
複製代碼
在開發移動端的時候,會遇到 input
的 placeholder
垂直方向不居中的狀況。
input
的placeholder
會出現文本位置偏上的狀況:PC端設置line-height
等於height
可以對齊,而移動端仍然是偏上,解決方案時是設置css line-height:normal
;
html:
<input class="input" />
複製代碼
樣式:
.input{
line-height:normal;
}
複製代碼
在ios
頁面向上向下滑動的過程當中,會出現卡頓,不流暢的現象,具體問題以下:
1 在safari
上,使用了-webkit-overflow-scrolling:touch
以後,頁面偶爾會卡住不動。(中招) 2 在safari
上,點擊其餘區域,再在滾動區域滑動,滾動條沒法滾動的(中招)。
在解決這個問題以前,咱們先理解-webkit-overflow-scrolling
的兩個屬性
1 auto
: 使用普通滾動, 當手指從觸摸屏上移開,滾動會當即中止。 2 touch
: 使用具備回彈效果的滾動,當手指從觸摸屏上移開,內容會繼續保持一段時間的滾動效果。繼續滾動的速度和持續的時間和滾動手勢的強烈程度成正比。同時也會建立一個新的堆棧上下文。
<div id="app" style="-webkit-overflow-scrolling: touch; ">
<div style="min-height:101%"></div>
</div>
複製代碼
或
<div id="app" style="-webkit-overflow-scrolling: touch; ">
<div style="height:calc(100%+1px)"></div>
</div>
複製代碼
方法就是在webkit-overflow-scrolling:touch
屬性的下一層子元素上, 將height
加1%或1px。從而主動觸發scrollbar
。
若是沒有使用taro
等跨平臺框架構建的h5,當在M端展現h5的時候,雙擊或者雙指張開手指頁面元素,頁面會放大或縮小。
針對這個狀況,實際不算一個bug
,由於html
自己就支持縮放。在pc
端的時候,咱們能夠控制鼠標滾輪控制頁面縮放,可是在移動端這個行爲也存在。可是對於嵌入的 M端 h5頁面,咱們不須要這個功能。
咱們能夠經過 meta
元標籤標準中有個 中 viewport
屬性,用來控制頁面的縮放,通常用於移動端。
咱們先看看taro-h5
是怎麼適配的.
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
複製代碼
核心user-scalable=no
,沒錯,就是經過這個屬性來阻止縮放行爲的。
在用taro-vue
構建 h5
應用的時候,對於banner
輪播圖部分,出現一個詭異的問題,就是水平方向輪播的時候,指望圖片是正常的輪播效果,可是初始化的時候,圖片垂直方向平鋪。
大體效果以下圖所示:
指望結果
實際結果
大體代碼以下:
<swiper class="swiper-wrap" >
<swiper-item v-for="(v,idx) in renderList" :key="idx" class="swiper-item" >
<view class="swiper-wrap-item">
<image mode="widthFix" :src="v.path" class="swiper-image" />
</view>
</swiper-item>
</swiper>
複製代碼
這個棘手的問題在於不是每次都復現,因爲這個頁面是商品詳情頁,問題會根據某一個商品出現。由於 renderList
是經過後臺獲取的圖片列表,因此判斷問題是由渲染swiper
-> 請求數據賦值renderList
-> 再到swiper-item
渲染圖片列表的過程當中,某一個環節出了問題。遂改變了渲染方案, 因此採用 獲取數據 -> 渲染swiper ->渲染swiperItem的方案。
改進後的代碼以下:
<swiper class="swiper-wrap" v-if="renderList.length > 0" >
<swiper-item v-for="(v,idx) in renderList" :key="idx" class="swiper-item" >
<view class="swiper-wrap-item">
<image mode="widthFix" :src="v.path" class="swiper-image" />
</view>
</swiper-item>
</swiper>
複製代碼
當 renderList
獲取到數據以後,在依次渲染swiper
,swiper-item
。根本解決了這個問題。
如下在開發小程序的過程當中遇到的兼容問題。
在微信小程序裏開發webview h5
的時候,在配置了合法域名,域名備案的狀況下,出現了 ios
上正常打開,可是在 android
手機上出現了被攔截的狀況。並且這些狀況都是由於打開webview
的 url
中存在漢字的狀況。
效果圖片
實際緣由很簡單,安卓手機對於 http / https
url若是存在漢字,須要用encodeURI
對漢字進行編碼處理就能夠了。
<web-view :src="webViewUrl" @message="handerMessage" />
複製代碼
this.webViewUrl = commonUrl + '/pages/goods/index?name=' + encodeURI('外星人')
複製代碼
若是是接口請求,就這麼寫
wx.request({
url: commonUrl + '/pages/goods/index?name=' + encodeURI('外星人'),
method: "GET",
})
複製代碼
完美解決了問題。
關於微信小程序中webview
被攔截。我總結了一個詳細的方案,供你們參考,也是開發中踩坑實錄。
若是在微信小程序開發webview
中 , 被微信攔截,你須要這樣逐一排查。
首先檢查域名是否備案,若是域名沒有備案,是沒法正常打開webview
的,若是當前域名是二級域名
,那就看主域名有沒有備案,二級域名無需獨立備案。
配置業務域名流程很簡單,首先登錄小程序後臺 -> 開發,開發管理 - > 開發設置。
而後選擇業務域名 -> 點擊修改 -> 添加業務域名。
注意上邊這部分,須要按這上面的操做添加。添加成功後,會自動添加到,合法域名列表中。
若是走完上邊的兩步,仍然被攔截。在2020年以前的域名,通常不會被攔截,可是微信對新申請的域名比較嚴格,須要先點擊申訴試試,若是申訴還不行的話,須要聯繫微信團隊相關人員解決問題,由於咱們公司有與微信團隊聯繫的部門,因此無須咱們聯繫。
若是隻有安卓手機被攔截的狀況,請按照上面的方法,編碼帶漢字的url
。
微信小程序在iphone低版本手機(iphone6 ,6p),若是多個視圖容器排列(水平和豎直方向都會存在),可能會出現個別邊框顯示不全的問題。
效果以下圖所示:
<view class="father" >
<view class="item" >商品1</view>
<view class="item" >商品2</view>
<view class="item" >商品3</view>
<view class="item" >商品4</view>
</view>
複製代碼
.father{
width: 696rpx;
height: 60rpx;
font-size: 28rpx;
color: #01b5b5;
margin: 0 auto;
}
.item{
height: 60rpx;
line-height: 60rpx;
border: 1rpx solid #01b5b5;
float: left;
border-radius: 10rpx;
padding: 0 20rpx;
margin-right: 16rpx;
margin-bottom: 16rpx;
}
複製代碼
通過測試得來一組數據 ,注意步驟1中加粗的文本.label-con類中width:696rpx,將標籤的父容器寬度設置爲下面的值都會出現這個692 693 696 697 700 701 704 705 708 709。咱們把這組數字除以2。
692/2=346
,693/2=346.5
,696/2=348
,697/2=348.5
,700/2=350
,701/2=350.5
,704/2=352
,705/2=352.5
,708/2=354
,709/2=354.5
**分析結果:**當標籤的父容器寬度(單位rpx)÷2的值爲偶數或偶數.5的時候會出現該bug,那麼咱們能夠推到出用200.52=401,3022=604等等都會重現這個bug。那麼解決方案油然而生。
第一種方式是設置標籤父容器的寬度到無bug值,即(奇數或奇數.5)2,例如2812rpx,281.5*2rpx能夠解決;
<view class="father" >
<view class="hold" />
<view class="item" >商品1</view>
<view class="item" >商品2</view>
<view class="item" >商品3</view>
<view class="item" >商品4</view>
</view>
複製代碼
.hold{
width: 1rpx;
height: 100%;
float: left;
}
複製代碼
效果以下,完美的解決了這個問題。
相信不少同窗在開發微信小程序的時候都會遇到scroll-view
不滑動的狀況,形成scroll-view
不滑動的緣由有會多,橫向和豎向不滑動的緣由也不一樣,接下來我會分別從橫向和豎向分別介紹形成滑動的緣由。
橫向:
豎向:
對於豎直方向的滑動,形成緣由以下:
① scroll-view
的 scroll-y
是否爲 true
<scroll-view :scroll-y="true" >
<!-- 此處省略不少東西 -->
</scroll-view>
複製代碼
② scroll-view
必須設置具體的高度,若是沒有設置高度,或者直接繼承父元素高度100%
,那麼 scroll-view
豎直方向將無效。咱們必須動態獲取scroll-height
由於在不一樣型號手機,都要達到完美的效果
如何正確獲取scroll-view
高度
狀況一 scroll-view
在中間的狀況:
const scrollHeight = windowHeight - scrollTop - scrollBottom
複製代碼
狀況二 scroll-view
靠底部的狀況 :
const scrollHeight = windowHeight - scrollTop
複製代碼
③ 檢查 scroll-view 是否設置了 overflow-y: auto;
等滑動屬性。
<scroll-view :scroll-y="true" class="scroll_box" >
<!-- 此處省略不少東西 -->
</scroll-view>
複製代碼
.scroll_box{
height:500px;
overflow-y: auto;
}
複製代碼
對於水平方向的滑動,形成緣由以下:
① scroll-view
的 scroll-x
是否爲 true
<scroll-view :scroll-x="true" >
<!-- 此處省略不少東西 -->
</scroll-view>
複製代碼
② 不要設置 display:flex;
等狀況 ,讓子元素設置 display:inline-block
<scroll-view :scroll-x="true" class="scroll_box" >
<view class="item" > <!-- 此處省略不少東西 --> </view>
<view class="item" > <!-- 此處省略不少東西 --> </view>
<view class="item" > <!-- 此處省略不少東西 --> </view>
<!-- .... -->
</scroll-view>
複製代碼
.scroll_box{
/* display:flex; 不要這麼作 */
white-space: nowrap;
}
.item{
display:inline-block; /* 這麼作 */
}
複製代碼
③ scroll-view
設置樣式 white-space: nowrap;
<scroll-view :scroll-x="true" style="white-space: nowrap;" ></scroll-view>
複製代碼
這個是好久以前作的一個相似地圖的項目,在地圖組件上,有一個view
,在高版本手機上,正常顯示,可是在低版本安卓手機上,會出現view
只有文字能看見,背景徹底被原生組件覆蓋,設置層級也沒有效果。
後來差了微信文檔,才明白原生組件和原生組件的限制。
小程序中的部分組件是由客戶端建立的原生組件,這些組件有:
camera canvas input(僅在focus時表現爲原生組件) live-player live-pusher map textarea video
因爲原生組件脫離在 WebView 渲染流程外,所以在使用時有如下限制:
①原生組件的層級是最高的,因此頁面中的其餘組件不管設置 z-index 爲多少,都沒法蓋在原生組件上。後插入的原生組件能夠覆蓋以前的原生組件。
②原生組件還沒法在 picker-view 中使用。基礎庫 2.4.4 如下版本,原生組件不支持在 scroll-view、swiper、movable-view 中使用。
③部分CSS樣式沒法應用於原生組件,例如:沒法對原生組件設置 CSS 動畫,沒法定義原生組件爲 position: fixed,不能在父級節點使用 overflow: hidden 來裁剪原生組件的顯示區域。
④原生組件的事件監聽不能使用 bind:eventname 的寫法,只支持 bindeventname。原生組件也不支持 catch 和 capture 的事件綁定方式。原生組件會遮擋 vConsole 彈出的調試面板。 在工具上,原生組件是用web組件模擬的,所以不少狀況並不能很好的還原真機的表現,建議開發者在使用到原生組件時儘可能在真機上進行調試。*
cover-view
與 cover-image
爲了解決原生組件層級最高的限制。小程序專門提供了 cover-view
和 cover-image
組件,能夠覆蓋在部分原生組件上面。這兩個組件也是原生組件,可是使用限制與其餘原生組件有所不一樣。
ios
環境下,scroll-view
標籤裏面若是有,position:absolute
的元素。當scroll-view
滑動的過程當中,定位的元素會出現抖動的狀況。
🤔分析緣由,仍是 scroll-view
和 ios
兼容性的緣由形成的。
針對這個抖動問題,解決方案也是很簡單,咱們把定位的元素從scroll-view
拿出來。就能根本解決這個問題。
<view class="box" >
<scroll-view class="scroll_box" :scroll-y="true" >
<view class="current" >我是定位元素</view>
</scroll-view>
</view>
複製代碼
.box{
}
.scroll_box{
height:500px;
overflow-y: auto;
position:relative;
}
.current{
position:absolute;
left:0;
top:0;
}
複製代碼
改爲
<view class="box" >
<scroll-view class="scroll_box" :scroll-y="true" >
</scroll-view>
<view class="current" >我是定位元素</view>
</view>
複製代碼
.box{
position:relative;
}
.scroll_box{
height:500px;
overflow-y: auto;
}
.current{
position:absolute;
left:0;
top:0;
}
複製代碼
在開發小程序的時候,有一個小程序跳轉另一個小程序的場景,第一次的時候沒有任何問題,可是當從跳轉的目標小程序,返回到當前小程序以後,第二次跳轉的時候,發現跳轉功能失效了,沒法再次跳轉。咱們的跳轉邏輯是寫在一個小程序過渡頁面的生命週期中的。具體流程圖以下所示:
先看看跳轉小程序方法
wx.navigateToMiniProgram({
appId:'appId',
path:'路徑',
extraData:'須要傳遞給小程序的數據',
success(){}, // 成功回調
fail(){}, //失敗回調
complete(){} //不管成功/失敗,都會執行完成方法。
})
複製代碼
🤔這究竟是爲何呢,這個問題困擾我好久,查閱了相關資料,微信文檔都沒找到相關的解決方案。可是微信文檔有這麼一句話,須要用戶觸發跳轉,從 2.3.0 版本開始,若用戶未點擊小程序頁面任意位置,則開發者將沒法調用此接口自動跳轉至其餘小程序 最後發現是第二次跳轉的過程當中,因爲不是用戶主動行爲(點擊事件等人爲主動的行爲),而是又過渡頁面的生命週期執行的跳轉小程序,因此微信被斷定無效的跳轉,就會直接走跳轉失敗的邏輯,webview
裏面的點擊跳轉事件不算是用戶的主動行爲😂😂。
因此咱們在過渡頁進行一判斷,若是是第二次跳轉,先彈出彈窗,讓用戶主動點擊,觸發用戶主動行爲。而後再跳轉小程序。
在用taro-vue
搭建小程序的時候,在scroll-view
向下滑動的時候,會出現一個詭異狀況,就是scroll-view
會由於一個兄弟元素的顯示隱藏,而忽然置頂。
結構是這樣的。
<view>
<scroll-view :scroll-y="true" >
<!-- 此處省略不少 -->
</scroll-view>
<view class="current" v-show="currentShow" > </view>
</view>
複製代碼
當scroll-view
滑動的時候,想用變量currentShow
控制scroll-view
顯示隱藏,可是 currentShow
一旦改變,就會引發 scroll-view
忽然置頂。
scroll-view
的問題還真是多呀,這個問題曾困擾筆者好久, taro3.0 taro-vue
畢竟不夠成熟,會有不少想象不到的問題,若是想用taro
,我這裏推薦taro2.0
比較成熟。
廢話很少說,這裏介紹兩個解決方案。
1 將當前元素節點放在 scroll-view
元素內部。
<view>
<scroll-view :scroll-y="true" >
<!-- 此處省略不少 -->
<view class="current" v-show="currentShow" > </view>
</scroll-view>
</view>
複製代碼
2 將v-if
改變成 v-show
<view>
<scroll-view :scroll-y="true" >
<!-- 此處省略不少 -->
</scroll-view>
<view class="current" v-if="currentShow" > </view>
</view>
複製代碼
① 關於canvas 寬高以及縮放比問題,繪製的元素變形,畫布的高度真得等於cavans標籤設置的寬高麼?
② canvas怎麼繪製疊在一塊兒的兩張圖片,並控制層級?
③ 如何用canvas繪製,多行文本?
④ 如何根據設計稿,精確還原海報各個元素位置問題。
⑤ canvas怎麼繪製base64的圖片?
⑥ 如何繪製網絡的圖片,兩種canvas畫布api,繪製圖片有什麼區別完成?
① 如何正確選型生成二維碼工具?
② 生成的二維碼,識別不出來怎麼辦?
③ 如何繪製二維碼上的logo?
這些問題都會在筆者的另外一篇文章中找到答案,文章的傳送門是:
這些問題都是筆者在實際工做中遇到的問題,吐血總結踩坑實錄,爲了讓你們少走彎路。送人玫瑰,手留餘香,閱讀的朋友能夠給筆者點贊,關注一波 ,陸續更新前端超硬核文章。
回看筆者往期高贊文章,有更多精彩內容等着你!
「react進階」年終送給react開發者的八條優化建議 800+
贊👍
Vue組件通訊方式及其應用場景總結 250+
贊👍
h5,小程序飛入購物車(拋物線繪製運動軌跡點) 300
贊 👍
vue3.0源碼系列
vue3.0 響應式原理(超詳細) 200+
贊👍
全面解析 vue3.0 diff算法 100+
贊👍
vue3.0 watch 和 computed源碼解析 30+
贊👍
react-hooks系列
玩轉react-hooks,自定義hooks設計模式及其實戰 150+
👍贊
react-hooks如何使用 70+
贊👍
開源項目系列
230+
贊 👍順便透露一下,接下來會發布一篇,react-keepalive-router
系列第二篇文章,完善功能。