摘要:定位問題根據調用棧很快定位到了代碼,源碼定位到之前一位同事寫的組件代碼,大概是這樣的部分業務代碼報錯的地方部分業務代碼發現是觸發了事件,因為沒有這個字段,導致拋出異常。它的和鼠標事件很像,非常容易遷移。
</>復制代碼
同步自我的博客,歡迎交流
這篇文章在草稿箱里躺了很久,因為最近又遇到了相關問題,于是又整理了一下。請注意這里講的不是 css 的 pointer-events。
起因從某個月黑風高的晚上開始,有人發現我們的 web-app 在 Chrome 模擬器里開始出現報錯,報錯信息大概就是下面這樣。
</>復制代碼
VM1023:1 Uncaught TypeError: Cannot read property "0" of undefined
但是只有他的瀏覽器有問題,而且對功能毫無影響,本著在我的機器上不復現的精神(好吧,當時比較忙),這個問題的優先級排的不高,但是后面一段時間慢慢有人也出現相同的問題,于是我開始在意這個問題了。
定位問題根據調用棧很快定位到了代碼,源碼定位到之前一位同事寫的組件代碼,大概是這樣的:
</>復制代碼
dom.on("touchstart pointerdown", function (event) {
/*部分業務代碼*/
var touch = event.touches[0]; //報錯的地方
/*部分業務代碼*/
})
debug 發現是觸發了 pointdown 事件,因為 event 沒有 touches 這個字段,導致拋出異常。但是之前用的好好的呀,難道是瀏覽器的 API 變化了?而且我也沒有了解過 pointerdown 事件,這個事件是用來處理什么的呢?于是我帶著兩個問題開啟了搜索之旅:
什么是 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 事件提供了一些特有的事件屬性
pointerId:當前指針事件的唯一標識,主要是在多點觸控時標識唯一的一個輸入源
width:接觸面的寬度
height:接觸面的高度
pressure:接觸的壓力值,范圍是0-1,對于不支持壓力的硬件,比如鼠標,按壓時該值必須為 0.5,否則為 0
tiltX,titltY:手寫筆的角度
pointerType:事件類型,目前有 mouse,pen,touch,如果是無法探測的指針類型,則該值為空字符串
isPrimary:用于標識是否是主指針,主要是在多點觸控中生效,開發者也可以通過忽略非主指針的指針事件來實現單點觸控。
如何確定主指針:
鼠標輸入:一定是主指針
觸摸輸入:如果 pointerdown 觸發時沒有其他激活的觸摸事件,isPrimary 為 true
手寫筆輸入:與觸摸事件類似,pointerdown 觸發時沒有其他激活的 pointer 事件
相關事件事件名稱 | 作用 |
---|---|
pointerover | 與 mouseover 行為一致 |
pointerenter | 與 mouseenter 行為一致 |
pointerdown | 指針進入活動狀態,比如觸摸了屏幕,類似于 touchstart |
pointermove | 指針進行了移動 |
pointerup | 指針取消活動狀態,比如手指離開了屏幕,類似于 touchend |
pointercancel | 類似于 touchcancel |
pointerout | 指針離開元素邊緣或者離開屏幕,類似于 mouseout |
pointerleave | 類似于 mouseleave |
gotpointercapture | 元素捕獲到指針事件時觸發 |
lostpointercapture | 指針被釋放時觸發 |
可以看到,pointer 事件與已知的事件類型基本一致,但是有一點區別:在觸摸屏上,我們可能會滑動屏幕來觸發頁面滾動,縮放或者刷新,對于 touch 事件,這時會觸發 touchmove,但是對于 pointer 事件,當觸發這些瀏覽器行為時,你卻會接收到 pointercancel 事件以便于通知你瀏覽器已經接管了你的指針事件。
如何檢測首先,pointer 事件的支持程度已經很不錯了,你可以使用 Pointer Events polyfill來進行兼容,也可以自行檢測
</>復制代碼
if (window.PointerEvent) {
// 支持
} else {
// 不支持
}
導致問題的原因
這時候,對于本文一開始提到的問題就顯而易見了,因為 point events 是沒有 touches 這個屬性的。那么我們還有兩個問題。
為什么之前會用到 point events?后來我看了下 zepto 的源碼,在事件處理時是考慮到了 point event 的,同事之前寫的代碼大概是參考了 zepto 的事件系統。
為什么會突然爆發這個問題?很簡答,Chrome 55 開始支持這個 API,Chrome 具體的支持信息可以參考官方日志,至于怎么檢測瀏覽器支持,可以參考上面的內容
總結對于開發來說,一定要鉆進去,任何 bug 都是有原因的
代碼報錯應該有相應的監控機制,讓機器來幫我們發現問題,而不是靠人工去干預
參考
https://www.w3.org/Submission...
https://developers.google.com...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82984.html
摘要:類型不同導致的問題結果如下我們發現當為數字的時候,是不會進行去重的導致的類型轉換結果我們發現通過之后都變成了類型 array_merge 類型不同導致的問題 $a = [1=>php,2=>mysql,3=>redis]; $c = [1=>zabbix,2=>mysql]; $d = array_merge($a,$c); var_dump($d); 結果如下 array(5) {...
摘要:解決開發使用的是的框架,在中配置的是然而,在中,通過發現的有兩個用戶的紀錄,一個是,另一個是空,即當使用的用戶是非時,訪問的是時,就會報這個錯。解決辦法將修改為。。,的,只不過的配置導致了不同的結果。 SQLSTATE[HY000] [2002] No such file or directory 解決Trace 開發使用的是PHP的Yii2框架,在config/db.php中配置的h...
閱讀 2594·2023-04-26 03:00
閱讀 1408·2021-10-12 10:12
閱讀 4204·2021-09-22 15:33
閱讀 2931·2021-09-22 15:06
閱讀 1544·2019-08-30 15:44
閱讀 2155·2019-08-30 13:59
閱讀 543·2019-08-30 11:24
閱讀 2429·2019-08-29 17:07