
最近在開發(fā) chrome 的插件,方便微博用戶下載圖片和視頻。
開發(fā)的過程中遇到很多問題,這邊就記錄一下關(guān)于快捷鍵的問題。方便遇到相同問題的小伙伴能參考。
現(xiàn)有問題
在 chrome 插件開發(fā)過程中,需要在既有網(wǎng)頁里插入一個(gè)界面,這個(gè)界面需要輸入一些內(nèi)容,當(dāng)輸入的時(shí)候就會(huì)觸發(fā)微博的快捷鍵。


這種體驗(yàn)用戶肯定接受不了,那么就要想辦法控制這個(gè)快捷鍵的觸發(fā)。
解決思路
想要看結(jié)果的接著往下翻?這里講整個(gè)過程
一開始為了解決問題,需要了解一下微博的快捷鍵邏輯是怎么設(shè)計(jì)的。
快捷鍵功能的是通過 keydown 和 keyup 事件觸發(fā)的
所以先去看一下 dom 上哪里監(jiān)聽了這兩個(gè)事件,在 html 節(jié)點(diǎn)上找到了3個(gè)監(jiān)聽

通過這里鏈接的源碼,最后分析出
微博快捷鍵通過 STK.hotKey 接口來注冊(cè)和移除

既然找到了監(jiān)聽的位置,接著就想能不能移除這些監(jiān)聽。
Chrome 插件是無法獲取網(wǎng)頁 window 對(duì)象的,只能獲取到 dom 對(duì)象
由于 chrome 插件開發(fā)在安全方面的考慮,插件沒法得到 window 對(duì)象,那么通過微博接口破解就沒有辦法了。
只得想辦法通過 dom 來處理。去查一下文檔看看有沒有什么新發(fā)現(xiàn)。

Element 繼承了EventTarget,那么接著看看這個(gè)上面有什么方法.

Sad,這里除了 add 和 remove 沒有更多的方法了,removeEventListener 是沒有辦法使用的
要通過 removeEventListener 移除監(jiān)聽就必須要有注冊(cè)監(jiān)聽時(shí)的函數(shù)對(duì)象。
有點(diǎn)無路可走的心情,有點(diǎn)無法理解為什么無法獲取到一個(gè) dom 上綁定的監(jiān)聽列表,也沒有辦法簡單的移除一個(gè)監(jiān)聽。(大概是安全考慮吧)
在網(wǎng)路上各種搜索后,發(fā)現(xiàn)了一絲線索,關(guān)于事件的傳遞。
事件既然可以傳遞,那么就有相應(yīng)的方法攔截
事件的傳遞方式有兩種:捕獲和冒泡
阻止事件的傳遞有兩個(gè)方法:stopPropagation 和 stopImmediatePropagation
event.stopPropagation() 可以從下一個(gè)節(jié)點(diǎn)阻止事件傳播
event.stopImmediatePropagation() 可以從當(dāng)前節(jié)點(diǎn)阻止事件傳播
但是當(dāng)前節(jié)點(diǎn)已經(jīng)觸發(fā)的事件無法阻止
這是什么意思呢,就是如果能成為節(jié)點(diǎn)上第一個(gè)注冊(cè)的事件,那就有權(quán)利阻止隨后注冊(cè)的事件被觸發(fā)(同一個(gè)事件名)
知道有這樣的方法后就有辦法解決了,讓 chrome 插件在網(wǎng)頁加載前加載,并成為 html 元素上第一個(gè)注冊(cè) keydown keyup 事件,那么就可以在需要的時(shí)候禁止快捷鍵被觸發(fā)。
解決方法
// chrome 插件 manifest 配置
// 在網(wǎng)頁加載前運(yùn)行插件
"content_scripts": [
{
"js": [
"jquery.min.js"
"app.js"
],
"run_at": "document_start"
}
]
// chrome 插件 content_scripts
// app.js
$(document).ready(function () {
window.Weibo = {
disableKeyEvent: false
}
document.querySelector('html').addEventListener('keyup', function keydown (e) {
if (window.Weibo.disableKeyEvent) {
e.stopImmediatePropagation();
}
})
document.querySelector('html').addEventListener('keydown', function keydown (e) {
if (window.Weibo.disableKeyEvent) {
e.stopImmediatePropagation();
}
})
})

在 window(插件的 window)上綁定了一個(gè)變量來控制是否禁止快捷鍵功能,這樣技能保留微博快捷鍵的功能,也能在我需要輸入文本的時(shí)候不打擾用戶體驗(yàn)。
總結(jié)
- 快捷鍵功能的是通過 keydown 和 keyup 事件觸發(fā)的
- 微博快捷鍵通過 STK.hotKey 接口來注冊(cè)和移除
- Chrome 插件是無法獲取網(wǎng)頁 window 對(duì)象的,只能獲取到 dom 對(duì)象
- event.stopPropagation() 可以從下一個(gè)節(jié)點(diǎn)阻止事件傳播
- event.stopImmediatePropagation() 可以從當(dāng)前節(jié)點(diǎn)阻止事件傳播
但是當(dāng)前節(jié)點(diǎn)已經(jīng)觸發(fā)的事件無法阻止
JSbin
羅小黑寫寫文字
如果喜歡文章 請(qǐng)留下一個(gè)贊~
如果喜歡文章 分享給更多人~自由轉(zhuǎn)載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證)
轉(zhuǎn)載時(shí)請(qǐng)保留原文鏈接 以保證可及時(shí)獲取對(duì)文章的訂正和修改