通過一次報錯詳細談談Point事件

2022-09-27 09:18:07 字數 2780 閱讀 6750

前言

起因從某個月黑風高的晚上開始,有人發現我們的 web-app 在 chrome 模擬器裡開始出現報錯,報錯資訊大概就是下面這樣。

vm1023:1 uncaught typeerror: cannot read property '0' of undefined

但是只有他的瀏覽器有問題,而且對功能毫無影響,本著在我的機器上不復現的精神(好吧,當時比較忙),這個問題的優先順序排的不高,但是後面一段時間慢慢有人也出現相同的問題,於是我開始在意這個問題了。

定位問題

根據呼叫棧很快定位到了**,原始碼定位到之前一位同事寫的元件**,大概是這樣的:

dom.on('touchstart pointerdown', function (event) )

debug 發現是觸發了 pointdown 事件,因為 event 沒有 touches 這個字段,導致丟擲異常。但是之前用的好好的呀,難道是瀏覽器的 api 變化了?而且我也沒有了解過 pointerdown 事件,這個事件是用來處理什麼的呢?於是我帶著兩個問題開啟了搜尋之旅:

聊聊 pointer events

查問題,最簡單的問題就是摟一遍 w3c 的官方文件了。這裡簡單說下我的理解。

裝置輸入形式的多樣化

在 pc 時代,我們通過滑鼠與螢幕互動,這時候,我們設計系統時只需要考慮滑鼠事件就好了。但是如今,有很多新的裝置,比如智慧型手機,平板電腦,他們包含了其他的輸入方式,比如觸控,手寫筆,官方也為這些輸入形式都提供了新的事件。

但是對於開發者來說,這是件很麻煩的事,因為這意味著你需要為你的網頁適配各種事件,比如你要根據使用者的移動來畫圖,你需要相容 pc 和手機,你的**可能就會是下面這樣

dom.addeventlistener('mousemove',

draw);

dom.addeventlistener('touchmove',

draw);

如果需要相容更多的輸入裝置呢?比如手寫筆,這樣的話**就會很複雜。而且,為了相容現有的基於滑鼠事件的**,很多瀏覽器都會為所有的輸入型別觸發滑鼠事件(例如在 touchmove 時觸發 mousemove,我在 chrome 試驗了一下不會觸發,但是因為沒有裝置,手寫筆的情況沒有試),這也會導致無法確認是否真的是滑鼠觸發的事件。

如何相容多種輸入形式

為了解決這一系列的問題,w3c 定義了一種新的輸入形式,即 pointer。任何由滑鼠、觸控、手寫筆或者其他輸入裝置在螢幕上觸發的接觸,都算是 pointer 事件。

它的 api 和滑鼠事件很像,非常容易遷移。除了提供滑鼠事件常用的屬性,比如 clientx,target 等等,還提供了一些用於其他輸入裝置的屬性,比如壓力,接觸面,傾斜角度等等,這樣開發者就可以利用 pointer 事件為所有的輸入裝置開發自己的功能了!

提供的屬性

pointer 事件提供了一些特有的事件屬性

如何確定主指標:

滑鼠輸入:一定是主指標

觸控輸入:如果 pointerdown 觸發時沒有其他啟用的觸控事件,isprimary 為 true

手寫筆輸入:與觸控事件類似,pointerdown 觸發時沒有其他啟用的 pointer 事件

相關事件

事件名稱

作用pointerover

與 mouseover 行為一致

pointerenter

與 mouseenter 行為一致

pointerdown

指標進入活動狀態,比如觸控了螢幕,類似於 touchstart

pointermove

指標進行了移動

pointerup

指標取消活動狀態,比如手指離開了螢幕,類似於 touchend

pointercancel

類似於 touchcancel

pointerout

指標離開元素邊緣或者離開螢幕,類似於 mouseout

pointerle**e

類似於 mousele**e

gotpointercapture

元素捕獲到指標事件時觸發

lostpointercapture

指標被釋放時觸發

可以看到,pointer 事件與已知的事件型別基本一致,但是有一點區別:在觸控螢幕上,我們可能會滑動螢幕來觸發頁面滾動,縮放或者重新整理,對於 t程式設計客棧ouch 事件,這時會觸發 touchmove,但是對於 pointer 事件,當觸發這些瀏twsifrmqhv覽器行為時,你卻會接收到 pointercancel 事件以便於通知程式設計客棧你瀏覽器已經接管了你的指標事件。

如何檢測

首先,pointer 事件的支援程度已經很不錯了,你可以使用 pointer events polyfill (本地**)來進行相容,也可以自行檢測

if (window.pointerevent) else

導致問題的原因

這時候,對於本文一開始提到的問題就顯而易見了,因為 point events 是沒有 touches 這個屬性的。那麼我們還有兩個問題。

為什麼之前會用到 point events?

後來我看了下 zepto 的原始碼,在事件處理時是考慮到了 point event 的,同事之前寫的**大概是參考了 zepto 的事件系統。

為什麼會突然爆發這個問題?

很簡答,chrome 55 開始支援這個 api,chrome 具體的支援資訊可以參考官方日誌,至於怎麼檢測瀏覽器支援,可以參考上面的內容

總結對於開發來說,一定要鑽進去,任何 bug 都是有原因的

**報錯應該有相應的監控機制,讓機器來幫我們發現問題,而不是靠人工去干預

參考本文標題: 通過一次報錯詳細談談point事件

本文位址:

App Store如何申請一次通過?

在申請之前,我們已經做好了起碼被拒絕4次以上,打長期持久戰的準備。我們在上個周一遞交了v1.0 版本的申請,然後忐忑等了10天之後,今天收到通知,一次性通過審核,已經上線。在說我們為此提前做了哪些準備之前,我們先說說之前在其他專案裡碰到過的鬧心的拒絕理由,這樣你就明白,為什麼我們這次居然還要寫乙個總...

App Store如何申請一次通過?

2019獨角獸企業重金招聘python工程師標準 在申請之前,我們已經做好了起碼被拒絕4次以上,打長期持久戰的準備。我們在上個周一遞交了v1.0 版本的申請,然後忐忑等了10天之後,今天收到通知,一次性通過審核,已經上線。在說我們為此提前做了哪些準備之前,我們先說說之前在其他專案裡碰到過的鬧心的拒絕...

記一次搞笑的報錯經歷

今天和同事聊天,突然聊到難忘的報錯,突然想起有一次很搞笑的經歷,覺得不錯想記下來。記得那時去年十月一前夕某天 啪,啪 鍵盤敲擊的聲音不斷,今天專案要上線,十月長假我就要來啦!努力一天懷著愉悅的心情進行最後乙個bug的修改以及測試 沒問題了 測試小姐姐說道。好啊 那上線 望著窗外朦朧的月光,明天下午要...