日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

滑动翻页效果实现和移动端click事件问题

發布時間:2024/1/8 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 滑动翻页效果实现和移动端click事件问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前述

本文很短~
主要是為了總結和講述移動端click和js事件機制導致的一個問題。
(:咳咳,其實幾句話就能寫完的還要水一篇文章,不愧是我…


正文

最近做了一個小活動,里面要用到一個效果:滑動翻頁。大概是這樣的:

<!-- HTML代碼 --> <div class="page-container"><div class="page" style="background: #dc3b26">1</div><div class="page" style="background: #f3b03d">2</div><div class="page" style="background: #44a2f8">3</div> </div>

在css中,首先因為是滑動翻頁,所以我們要保證“始終只有一屏”,這個可以放在全局樣式表里控制,然后是其中的“每一頁”都要占滿父元素 —— 這里其實用了“div是塊元素,無外力情況下豎直排列”的特性。

/** css樣式 */ html, body{margin: 0;padding: 0;width: 100%;height: 100vh;overflow: hidden;font-size: 60px; } .page-container{width: 100%;height: 100%; } .page-container .page{width: 100%;height: 100%; }

其JS實現也很簡單:因為在移動端,所以使用了touchstart、touchmove及touchend事件來實現手勢滑動功能:

  • start(剛按下)時記錄此時的手指位置——作為初始值;
  • 在move(觸摸滑動)時根據實時的手指位置和初始手指位置變量實現要求判斷,在本文場景為代表的場景下這一步一般還要求出“移動距離”實時賦值;
  • 在end(手指離開)時(也有直接在move時進行的)進行收尾工作——比如:圖片滑動完全劃過去、元素跑到結束位置、將事件監聽取消;
  • // 這里是控制全局js的文件 // 全局阻止瀏覽器默認行為 document.addEventListener("touchstart",function(e){if(e.cancelable){e.preventDefault();} },{passive: false}) // {passive: false}就是告訴前面可能有需要重置行為的代碼 document.addEventListener("touchmove",function(e){if(e.cancelable){e.preventDefault();} },{passive: false}) // JavaScript代碼 let curPageIndex=0; let pageContainer=document.querySelector(".page-container"); let pageNumber=pageContainer.children.length; //頁面的數量 // 文檔的視窗高度(這里就是一屏的高度) let cHeight=document.documentElement.clientHeight; // 設置頁面容器的margin-top為合適的值,讓其顯示在視野中 function toPage(){pageContainer.style.transition="all .5s ease";pageContainer.style.marginTop=-curPageIndex*cHeight+"px";// 變化完成后去掉過渡效果 !pageContainer.addEventListener("transitionend",function(){pageContainer.style.transition="none";},{once:true}) } toPage()pageContainer.ontouchstart=function(e){let y=e.changedTouches[0].clientY; //手指按下的縱坐標pageContainer.ontouchmove=function(e){let dis=e.changedTouches[0].clientY-y; //計算距離// 計算page-container的margin-toplet mtop=-curPageIndex*cHeight+disif(mtop>0){mtop=0;}else if(mtop<-(pageNumber-1)*cHeight){mtop=-(pageNumber-1)*cHeight;}// 實時改變位置pageContainer.style.marginTop=mtop+"px";}pageContainer.ontouchend=function(e){let dis=e.changedTouches[0].clientY-y;// 如果滑動距離實在太短,就回到滑動前的位置狀態if(Math.abs(dis)<=60){toPage()}else if(dis>0 && curPageIndex>0){curPageIndex--;toPage()}else if(dis<0 && curPageIndex<pageNumber-1){curPageIndex++;toPage()}// 手指離開后,取消監聽事件pageContainer.ontouchmove=null;pageContainer.ontouchend=null;} }

    至此,功能上似乎很完美。但這時候,我們在第一個page里添加一個button:

    <div class="page" style="background: #dc3b26"><button onclick="alert('哈哈哈')" class="but">click me!</button>1 </div>

    然后到頁面上查看效果:

    無效!

    這是因為在上方全局js文件里我們加了“阻止瀏覽器默認事件”的代碼。
    ——在移動端瀏覽器中,click事件和mousestart事件是同時被觸發的。因為移動端瀏覽器是沒有click事件的,它是由mouse事件模擬的! :也正是這個原因,才有了所謂的“移動端瀏覽器300ms延遲”的問題 1
    ——還有就是,在微信自帶的瀏覽器中,有一個“觸頂下拉回彈”的操作,這其實是不應該的。它也屬于瀏覽器默認事件。
    所以一般我們需要禁止掉這些東西。

    但是如上面所示,全部禁止掉總會造成一些困擾,怎么辦?
    H5提供了“自定義屬性”,針對本文方法,我們完全可以 —— 在全局事件里檢測當前觸發的元素有沒有某一個自定義屬性,如果有,就什么也不攔截;否則就執行禁止默認行為的代碼:
    比如

    <button data-default="true" onclick="alert('哈哈哈')" class="but">click me!</button>

    將上面“控制全局js的文件”內容改為如下:

    // 全局阻止瀏覽器默認行為 document.addEventListener("touchstart",function(e){if(e.target.dataset.default){return;}if(e.cancelable){e.preventDefault();} },{passive: false}) document.addEventListener("touchmove",function(e){if(e.target.dataset.default){return;}if(e.cancelable){e.preventDefault();} },{passive: false})

    就OK了:


    其實還有另一種“解法”:既然上面說了,移動端click實際上是通過mouse事件模擬的,那么我們可以從mousestart事件入手;又因為button元素是“第一個頁面”內的(子)元素,所以可以用阻止事件冒泡

    <!-- button就是普通的button --> <button class="but">click me!</button> document.querySelector(".but").addEventListener("touchstart",function(e){e.stopPropagation();alert('噶哈哈'); },false)

    關于捕獲和冒泡→

    我們首先要知道的是:當我們鼠標按下一個按鈕時,并不是“點擊了一個按鈕”,而是在這個區域內,鼠標(上的按鍵)被按下,操作系統和瀏覽器把這個信息對應到了“按鈕”所在區域并觸發其邏輯。
    事實上鼠標點擊并沒有位置信息,是操作系統一直在監聽鼠標移動,根據累積的位移計算出來的坐標,將其傳給瀏覽器。
    那么,把這個坐標轉換為具體的元素上的事件的過程,就可稱作“捕獲”。那“冒泡”呢?這個不好解釋,但有一點想必你是明白的:當你按下電視開關時,你也按到了電視!
    這就是很多文章會講到的“冒泡過程由內向外,捕獲過程由外向內”,或者說是“洋蔥模型”。
    還有一點就是:事件addEventListener的第三個參數 true/false ,即為“是捕獲/冒泡”。(別多想,這只是瀏覽器提供的事件模型之一。無論是否監聽,在一個事件發生時,捕獲和冒泡總是先后發生的)


  • 在一年多以前筆者曾寫過這篇文章(前端性能優化之移動端click:為何會有300ms延遲)說明這件事,不過里面只有解決方法,還很稚嫩。本文這里算是完善了吧。 ??

  • 總結

    以上是生活随笔為你收集整理的滑动翻页效果实现和移动端click事件问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。