記IOS下UIWebView的坑

ios在uiwebview下的坑

最近作了一個需求,須要作吸頂的效果,在安卓機器和IOS高版本系統下,能改完美實現吸頂效果,可是在低版本的IOS中,卻遇到了坑,當我滾動到吸頂的位置的時候,它仍然沒有吸頂,只有滾動中止的時候才吸頂。
vue

image

google分析了緣由,有兩種緣由會致使這種狀況。react

一、uiwebview下scroll事件只會在滾動中止時觸發

若是你監聽滾動是使用addEventListener的方式,那麼很遺憾的告訴你,你中招了,經過這種方式綁定滾動事件,如標題所示,只會在滾動中止的時候才觸發一次,相似防抖操做,只有在最後一次觸發。ios

可是,若是你用window.onscroll的方式監聽滾動的話,就能夠在滾動的過程當中觸發scroll事件了,是否是很神奇?web

網上還有說用touchmove來監聽,也是能夠在滾動的時候觸發事件的,可是touchmove有兩個缺點是:bash

  • 它觸發頻率低,就是須要滾動必定的距離纔會觸發
  • 它會慣性滾動,即咱們手指離開的時候,它還會模擬慣性滾動一段距離,而這個時候,無論是scroll仍是touchmove都沒法觸發。

然而,我改成onscroll監聽滾動了,但是我仍是沒法及時更新吸頂元素,仍是和用addEventListener來監聽scroll的效果同樣,在滾動中止的時候纔會吸頂。這就要導出第二個會致使這個現象的緣由了。框架

二、uiwebview下,scroll裏面的全部異步操做都會被阻塞

會出現這個的緣由,估計和第一個緣由同樣,IOS想要作一些優化,避免一些重複的操做,就和咱們作函數節流同樣的思想,可是出這個方案的大神,你就沒想到這樣一刀切的方式會讓咱們開發者遇到不少坑嗎(藉機吐槽下)?個人技術棧是用vue,而咱們知道,vue是異步更新dom的,因此我在onscroll裏面經過vue更新視圖的操做,都會被ios阻塞,只有滾動中止後纔會拿出來執行。dom

順便說一句,若是你的滾動處理函數使用防抖來優化,那效果仍是同樣,由於防抖的實現原理是setTimeout,而setTimeout也是異步操做,都會被IOS阻塞。異步

解決方案

具體看你們的狀況,若是是第一種緣由致使的,請使用window.onscroll來監聽滾動,若是是第二種緣由,請避免在scroll事件中使用異步操做,而若是你是使用vue或者react這些框架,它們都會異步去更新dom。函數

方案一

根據是不是uiwebview,選擇性地使用正常的方式和原生js操做dom更新視圖優化

if (isUIWebView) {
    window.onscroll = function() {
        // 使用原生js操做dom
    }
} else {
    // 正常的狀況,使用防抖、vue|react去操做dom
    window.addEventListener('scroll', this.scrollHandler)
}
複製代碼

方案二

使用第三方滾動插件模擬滾動,好比iscroll之類的。

其餘坑

  • os元素設置inline-block後元素下沉的問題

由於display: inline-block成了內聯,inline box有一個叫作baseline的東西,若是有的元素有多行文字,有的只有一行,就會以baseline爲基準,想要更改很簡單隻要vertical-align: top;和vertical-align: bottom;

  • 在ios的uiwebview下,pageYOffset屬性是無效的
    獻上獲取滾動距離的兼容性寫法
function getScrollTop(el) {
  if (!el) {
    return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
  }
  return el.scrollTop;
}
複製代碼
相關文章
相關標籤/搜索