React禁止頁面滾動踩坑實踐與方案梳理

最近在使用 React 技術(shù)棧重構(gòu)一個單頁應(yīng)用服猪,其中有個頁面是實現(xiàn)城市選擇功能近她,主要是根據(jù)城市的首字母來快速跳轉(zhuǎn)到相應(yīng)位置晌端,比較類似原生 APP 中的電話聯(lián)系人查找功能,頁面如圖


功能界面

主要問題

在上下滑動右側(cè) fixed 定位的元素時演痒,頁面會跟著一起滑動

滾動右側(cè)整個頁面跟著滾動

當然這個現(xiàn)象在開發(fā)過程中應(yīng)該會經(jīng)常遇到蹦锋,比如彈起 modal 框時千扔,如果 modal框的內(nèi)容高度小于框高度,滑動內(nèi)容也會導(dǎo)致頁面跟著滑動阅嘶, 那么在 React 中像往常一樣處理

<div className="nonius"
  id="nonius"
  onTouchStart={this.sidebarTouchStart.bind(this)}
  onTouchMove={this.sidebarTouchMove.bind(this)}
  onTouchEnd={this.sidebarTouchEnd.bind(this)}
>

使用 React 提供的事件綁定機制魂迄,分別綁定三個 handler 熊昌,在 onTouchMove 事件中昂利,我希望通過 preventDefault 能夠阻止父級元素的滾動

sidebarTouchMove(e) {
  e.preventDefault();
  ...
}

但實際的反饋卻事與愿違扩所,在調(diào)試中买羞,我發(fā)現(xiàn) Chrome 是有警告的婉徘,并且沒有達到想要的效果


chorme 開發(fā)工具警告提示

根據(jù)警告提示约炎,找到的原因是

AddEventListenerOptions defaults passive to false. With this change touchstart and touchmove listeners added to the document will default to passive:true (so that calls to preventDefault will be ignored)..
If the value is explicitly provided in the AddEventListenerOptions it will continue having the value specified by the page.
This is behind a flag starting in Chrome 54, and enabled by default in Chrome 56. See https://developers.google.com/web/updates/2017/01/scrolling-intervention

來源: https://www.chromestatus.com/features/5093566007214080

根據(jù) chrome 的提示得知,是因為 Chrome 現(xiàn)在默認把通過在 document 上綁定的事件監(jiān)聽器 passive 屬性(后面細說)默認置為 true,這樣就會導(dǎo)致我設(shè)置的 e.preventDefault() 被忽視了混槐。當然 Chrome 的這個做法是有道理捌刮,是為了提高頁面滾動的性能蛾派,那么為了防止帶來的副作用岂贩,官方考慮的很周到,給我們提供了一個 CSS 屬性專門用來解決這個問題

#fixed-div {
  touch-action: none;
}

In rare cases this change can result in unintended scrolling. This is usually easily addressed by applying a touch-action: nonestyle to the element where scrolling shouldn't occur.

https://developer.mozilla.org/zh-CN/docs/Web/CSS/touch-action

加上了這個屬性俊嗽,感覺世界總算和平了,But!在 ios 系統(tǒng)上測試發(fā)現(xiàn)税迷,這個屬性 x 用沒有,查了下 Can I Use


can i use 截圖

確定無誤,就是不支持外永,所以這個屬性只在 Chrome 安卓等機型下是支持的,ios 這個就用不了政钟,理想很豐滿驮履,顯示很骨感。既然不兼容口四,那只能降級處理了顺又,為了保證良好的功能體驗,感覺是還要從 passive 上做處理,說到 passive 根據(jù) MDN文檔:addEventListener 的介紹返弹,為了提高頁面滾動性能去团,大多瀏覽器都默認把 touchstart 和 touchmove 在文檔元素上直接注冊的這個事件監(jiān)聽器屬性設(shè)置成 passive:true 土陪,而通過 AddEventListener 注冊的事件依然沒有變化

既然現(xiàn)在默認將事件 passive 的屬性默認設(shè)置為 true ,那我就顯式設(shè)置為 false 好了源哩,查遍 React 的文檔坛掠,也沒發(fā)現(xiàn)事件監(jiān)聽器可以支持配置這個屬性的,在 github 上發(fā)現(xiàn)這個帖子 Support Passive Event Listeners #6436 目前看依然是 open 狀態(tài)的,現(xiàn)在不確定有沒有支持這個屬性

解決方案

既然這樣撤缴,只能單獨對 touchmove 通過 AddEventListener 方法去注冊事件監(jiān)聽了

// 為元素添加事件監(jiān)聽   
document.getElementById('nonius').addEventListener("touchmove", (e) => {
  // 執(zhí)行滾動回調(diào)
  this.sidebarTouchMove(e)
}, {
  passive: false //  禁止 passive 效果
})

加上這個方法后微宝,this.sidebarTouchMove(e) 方法中的 e.preventDefault() 方法就可以正常使用了,而且沒有警告提示虎眨,問題到此就算解決了

總結(jié)

總結(jié)下蟋软,這里的坑主要是 chrome 和 safari 平臺的標準不統(tǒng)一導(dǎo)致的,新的標準出臺嗽桩,其它宿主環(huán)境不能很好的支持岳守,當然 react 官方對這個屬性的支持也比較慢,同樣的前端 UI 框架 Vue 就處理的很棒


vue對passive屬性支持的相關(guān)語法

不小心暴露了碌冶,我是個 Vue粉湿痢,233
ok,完 ~

原文地址: http://w3cay.com/post/dc49b55.html?title=React-scroll&from=jianshu

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扑庞,一起剝皮案震驚了整個濱河市譬重,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌罐氨,老刑警劉巖臀规,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異栅隐,居然都是意外死亡以现,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門约啊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邑遏,“玉大人,你說我怎么就攤上這事恰矩〖呛校” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵外傅,是天一觀的道長纪吮。 經(jīng)常有香客問我,道長萎胰,這世上最難降的妖魔是什么碾盟? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮技竟,結(jié)果婚禮上冰肴,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好熙尉,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布联逻。 她就那樣靜靜地躺著,像睡著了一般检痰。 火紅的嫁衣襯著肌膚如雪包归。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天铅歼,我揣著相機與錄音公壤,去河邊找鬼。 笑死椎椰,一個胖子當著我的面吹牛境钟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俭识,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼慨削,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了套媚?” 一聲冷哼從身側(cè)響起缚态,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎堤瘤,沒想到半個月后玫芦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡本辐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年桥帆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慎皱。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡老虫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出茫多,到底是詐尸還是另有隱情祈匙,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布天揖,位于F島的核電站夺欲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏今膊。R本人自食惡果不足惜些阅,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斑唬。 院中可真熱鬧市埋,春花似錦黎泣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雪营。三九已至弓千,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間献起,已是汗流浹背洋访。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谴餐,地道東北人姻政。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像岂嗓,于是被迫代替她去往敵國和親汁展。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • ??JavaScript 與 HTML 之間的交互是通過事件實現(xiàn)的。 ??事件公罕,就是文檔或瀏覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,490評論 1 11
  • 我們知道滾動響應(yīng)是至關(guān)重要的在用戶移動端網(wǎng)站上觸摸的時候器紧,然而觸摸事件監(jiān)聽器經(jīng)常會導(dǎo)致嚴重的滾動性能問題。Chro...
    loushumei閱讀 2,133評論 0 4
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5楼眷? 答:HTML5是最新的HTML標準铲汪。 注意:講述HT...
    kismetajun閱讀 27,477評論 1 45
  • 光匆匆流逝,記憶永遠不老罐柳,每每翻開這些照片掌腰,與你們一同度過的歡樂時光仿佛還在昨天,時光無情张吉,記憶永存辅斟,歡樂的時光永...
    A顏妍閱讀 228評論 0 0
  • 創(chuàng)業(yè)是一個苦逼的事情士飒,不是每個人都可以創(chuàng)業(yè),不是創(chuàng)業(yè)的人都會成功蔗崎,很多的細節(jié)決定了你是否真正的創(chuàng)業(yè)酵幕,是否能夠成功。...
    管理老馬閱讀 189評論 1 1