摘要:業(yè)務(wù)邏輯業(yè)務(wù)邏輯在內(nèi),主要涉及的是按鍵事件交互處理以及檢索結(jié)果展示。目前,這個(gè)擴(kuò)展程序在說(shuō)明上貌似最新一版已經(jīng)是年的事了,看來(lái)作者也沒(méi)有繼續(xù)更新的打算了
前陣子在微博看到關(guān)于chrome書(shū)簽搜索的擴(kuò)展程序Holmes,于是使用了一下,確實(shí)還不錯(cuò),尤其書(shū)簽多很多的情況下,有個(gè)搜索功能 ,比定時(shí)做書(shū)簽分類(lèi)等等方便得多很多??粗鴶U(kuò)展程序功能簡(jiǎn)單,感覺(jué)實(shí)現(xiàn)應(yīng)該不難,于是我就試著查看一下擴(kuò)展程序源碼,也可以順便進(jìn)一步了解chrome擴(kuò)展程序的實(shí)現(xiàn)方法和操作api。
本篇文章意在講解Holmes的主要實(shí)現(xiàn),對(duì)于chrome擴(kuò)展程序怎么一步一步建立起來(lái),就不做重復(fù)說(shuō)明,網(wǎng)上搜索即可。
首先,既然要研究擴(kuò)展程序源碼,那么最直接的方式當(dāng)然就是從chrome安裝目錄來(lái)尋址該擴(kuò)展程序的所在目錄了。
這點(diǎn),其實(shí)網(wǎng)上有資料可以查看的,比如這里>>
步驟1,在chrome地址欄輸入:chrome://version 回車(chē),將結(jié)果頁(yè)中“個(gè)人資料路徑”一欄對(duì)應(yīng)的值復(fù)制(其實(shí)是一個(gè)目錄路徑)
步驟2,打開(kāi)資源管理器,鍵入剛復(fù)制的路徑,進(jìn)入目錄,打開(kāi)Extsions目錄,里面都是各種以字母組合的命名文件夾,對(duì)應(yīng)的其實(shí)是各個(gè)擴(kuò)展程序,命名其實(shí)是擴(kuò)展程序的id
步驟3,在地址欄輸入:chrome://extensions,進(jìn)入擴(kuò)展程序管理頁(yè),找到對(duì)應(yīng)的擴(kuò)展程序選項(xiàng),有ID,對(duì)應(yīng)的ID值就是對(duì)應(yīng)的擴(kuò)展程序文件夾名字。這似乎是個(gè)唯一值,holmes的ID是:gokficnebmomagijbakglkcmhdbchbhn
遵循上面三個(gè)步驟,我們就可以找到Holmes的擴(kuò)展程序目錄了 ,將其復(fù)制到方便查看的位置,就可以開(kāi)始查看源碼了。
理解配置做過(guò)擴(kuò)展程序的都知道,項(xiàng)目必須有一個(gè)配置文件manifest.json
這里列一下主要的配置字段,不全
{ "background": { "page": "watson.html" }, "browser_action": { "default_icon": "images/icon_19.png", "default_popup": "holmes.html", "default_title": "Holmes" }, "commands": { "_execute_browser_action": { "suggested_key": { "default": "Alt+Shift+H" } } }, "description": "Chrome Bookmark Search Extension", "icons": { "128": "images/icon_128.png", "16": "images/icon_19.png", "48": "images/icon_48.png" }, "manifest_version": 2, "minimum_chrome_version": "25", "name": "Holmes", "omnibox": { "keyword": "*" }, "permissions": [ "bookmarks", "tabs", "chrome://favicon/" ], "update_url": "https://clients2.google.com/service/update2/crx", "version": "3.2.1" }
可以看到,這里有個(gè)permissions字段,字面意義應(yīng)該是跟權(quán)限相關(guān),這里配置了bookmarks、tabs、和chrome://favicon/,這為后面要用到chrome的一些功能埋下了伏筆(這么說(shuō)好么?= =)
另外browse_action字段定義了點(diǎn)擊擴(kuò)展程序圖標(biāo)的一些行為,default_popup規(guī)定了點(diǎn)擊彈出框定位到holmes.html,也就是擴(kuò)展程序的業(yè)務(wù)頁(yè)面,即搜索框和搜索結(jié)果。
深入頁(yè)面找到holmes.html,查看頁(yè)面會(huì)發(fā)現(xiàn),頁(yè)面主要引入的js文件:
jquery 庫(kù)文件 fuse.min.js 模糊查詢(xún)工具 jquery.Core.js 基于jquery的核心方法 keymaster.min.js 按鍵事件工具 jquery.holmes.js 基于jquery的頁(yè)面業(yè)務(wù)邏輯
頁(yè)面的主要dom結(jié)構(gòu):
主要的節(jié)點(diǎn)是:輸入框 #pattern 和 搜索結(jié)果 #view.
到此,我們大概了解了holmes主要用到的是jquery來(lái)方便編程,利用keymaster來(lái)處理按鍵事件,利用fuse的模糊搜索來(lái)實(shí)現(xiàn)模糊查詢(xún)書(shū)簽。
那么,我們?cè)趺传@得chrome的書(shū)簽?zāi)??如果?shū)簽有增刪改,又該怎么辦呢?另外,我要怎么打開(kāi)標(biāo)簽頁(yè)來(lái)承載某個(gè)書(shū)簽?zāi)兀?/p> 獲取書(shū)簽和標(biāo)簽頁(yè)操作
獲取書(shū)簽,其實(shí)就呼應(yīng)了前面說(shuō)過(guò)的配置權(quán)限permissions.
我們?cè)趺粗赖模?首先定位到jquery.Core.js文件,文件內(nèi)容很簡(jiǎn)單,不過(guò)做了壓縮,這里我優(yōu)化了一下方便走讀。
(function() { var o, r; window.Holmes = { bookmarks: [], version: 3.21, showShortcutInfo: !1 }; r = function(o) { return function(o) { var e, t, n, a; for (a = [], t = 0, n = o.length; n > t; t++) { e = o[t]; if(e.hasOwnProperty("children")){ a.push(r(e.children)); }else{ if(e.url.match(/^javascript/)){ a.push(void 0); }else{ (e.title || (e.title = e.url), a.push(Holmes.bookmarks.push({ title: e.title, url: e.url }))); } } } return a } }(this); o = function() { return chrome.bookmarks.getTree(function(o) { return Holmes.bookmarks = [], r(o) }) }; chrome.bookmarks.onCreated.addListener(function(r, e) { return o() }); chrome.bookmarks.onRemoved.addListener(function(r, e) { return o() }); chrome.bookmarks.onChanged.addListener(function(r, e) { return o() }); Holmes.getPlaceholder = function() { var o; return o = ["Holmes at your service.", "How can I help you?", "It is a good day for searching.", "You know my methods. Apply them."], o[Math.floor(Math.random() * o.length)] }; o() }).call(this);
這里主要是定義了全局對(duì)象:Holmes,包含三個(gè)屬性,其中最主要的是bookmarks,它是一個(gè)數(shù)組,存儲(chǔ)chrome上的書(shū)簽,怎么存的呢?
在上述代碼上可以看出,通過(guò)調(diào)用chrome.bookmarks.getTree, chrome.bookmarks是chrome提供的書(shū)簽對(duì)象api,用于各種書(shū)簽操作,chrome書(shū)簽操作>>, 這里getTree就是獲取書(shū)簽樹(shù)結(jié)構(gòu),參數(shù)為回調(diào)函數(shù),從回調(diào)函數(shù)參數(shù)可以獲得樹(shù)節(jié)點(diǎn),通過(guò)children可以獲得子節(jié)點(diǎn),于是這里是實(shí)現(xiàn)對(duì)節(jié)點(diǎn)的處理 ,當(dāng)有children節(jié)點(diǎn)時(shí),遞歸操作,無(wú)則當(dāng)做鏈接獲取title跟url屬性,并push到bookmarks數(shù)組去(有可能收藏的是腳本代碼,這塊這里做了過(guò)濾處理)。
要用chrome.bookmarks,從官方文檔可知道, 需要配置permissions權(quán)限
{ "name": "My extension", ... "permissions": [ "bookmarks" ], ... }
另外,bookmarks對(duì)象還有事件處理函數(shù),這里用于更新書(shū)簽數(shù)據(jù)以備檢索。
chrome.bookmarks.onCreated.addListener chrome.bookmarks.onChangeed.addListener chrome.bookmarks.onRemoved.addListener
這里還沒(méi)涉及到tabs,但因?yàn)槎家渲?b>permissions,所以提前說(shuō)明,同樣,tabs也有官網(wǎng)文檔說(shuō)明
其配置權(quán)限類(lèi)似bookmarks,關(guān)于tabs的使用相當(dāng)簡(jiǎn)單:
chrome.tabs.create({url:xxx, pinned:true}) // 打開(kāi)標(biāo)簽頁(yè),url為鏈接, pinned是否固定標(biāo)簽頁(yè)
標(biāo)簽頁(yè)這里主要是打開(kāi)標(biāo)簽頁(yè),那就只需要用到這條api,其他可以到上面文檔說(shuō)明去查看。
業(yè)務(wù)邏輯業(yè)務(wù)邏輯在holmes.js內(nèi),主要涉及的是按鍵事件交互處理以及檢索結(jié)果展示。
對(duì)于檢索結(jié)果,其實(shí)是從全局對(duì)象Holmes.bookmarks入手, 對(duì)其采用fuse模糊搜索。
fuse的具體操作可以看 fuse官網(wǎng)
使用很簡(jiǎn)單,如下:
// 配置對(duì)象,檢索關(guān)鍵屬性 var option = { keys:["id"] }; // data為測(cè)試數(shù)據(jù) f = new Fuse(data, options); f.search("查找內(nèi)容"); //這里將對(duì)data的id屬性做 查找內(nèi)容 的搜索
在holmes里,使用很簡(jiǎn)單:在輸入框監(jiān)聽(tīng)keyup,清空結(jié)果dom($view), 對(duì)書(shū)簽數(shù)據(jù)進(jìn)行模糊查詢(xún)(鍵值:書(shū)簽標(biāo)題),得到結(jié)果調(diào)用updateView方法來(lái)給$view更新內(nèi)容。(涉及到鍵入監(jiān)聽(tīng),其實(shí)還可以考慮做節(jié)流操作避免重復(fù)執(zhí)行搜索)
代碼如下:
// 監(jiān)聽(tīng)輸入框keyup事件 $("#pattern").on("keyup", function(e) { var _kc, _ret, f, options; _kc = e.keyCode; if (_kc === 38 || _kc === 40 || _kc === 37 || _kc === 39) { $(this).css("-webkit-user-select", "text"); return false; } pattern = $("#pattern").val(); // 清空搜索結(jié)果 $view.html(""); _ret = []; if (pattern.length > 0) { pattern.replace(" ", ""); options = { keys: ["title"] }; // 對(duì)title進(jìn)行查詢(xún) f = new Fuse(Holmes.bookmarks, options); _ret = f.search(pattern); } else { _ret = []; search = null; } // 調(diào)用updateView對(duì)搜索結(jié)果進(jìn)行展示 return updateView(_ret); });
關(guān)于updateView: 已經(jīng)設(shè)定了bmarks_per_page變量用來(lái)定義結(jié)果顯示數(shù)量(并非把全部書(shū)簽結(jié)果都輸出,而是輸出前十條數(shù)據(jù)),并且對(duì)標(biāo)題進(jìn)行省略裁剪,并針對(duì)關(guān)鍵字插入span標(biāo)簽(可做樣式高亮,但擴(kuò)展程序并沒(méi)有做),在拼接dom模板時(shí)對(duì)首條數(shù)據(jù)加入current類(lèi),并且將對(duì)應(yīng)的dom保存到$current_mark,用于回車(chē)時(shí)直接打開(kāi)以及顯示選中項(xiàng),對(duì)拼接的dom添加到$view中,并且定義a標(biāo)簽點(diǎn)擊事件(由于每次搜索結(jié)果都是重新添加內(nèi)容,所以這里不會(huì)涉及重復(fù)綁定,但其實(shí)可以給$view做事件代理更佳)
代碼如下:
matchString = function(_string, _char_count) {
var _inp_val_pat;
_string = _string.length < _char_count ? _string : _string.substr(0, _char_count) + "...";
_inp_val_pat = new RegExp(pattern, "gi");
return _string.replace(_inp_val_pat, "" + _inp_val_pat.exec(_string) + "");
};
updateView = function(bmarks) {
var _classes, _match, _update, i, j, len, mark;
if (bmarks.length > 0) {
_update = "";
for (i = j = 0, len = bmarks.length; j < len; i = ++j) {
mark = bmarks[i];
// 我認(rèn)為這里直接break跳出循環(huán)即可,無(wú)需continue繼續(xù)循環(huán)
if (!(i < bmarks_per_page)) {
continue;
}
_classes = i === 0 ? "current" : "";
_match = matchString(mark.title, 50);
_update += "
ps:這里有個(gè)小知識(shí)點(diǎn),其實(shí)也涉及到permissions配置,在chrome下,chrome://favicon/+頁(yè)面地址 可以獲得該網(wǎng)站的favicon.
其他按鍵交互:除了輸入框鍵入字符的監(jiān)聽(tīng)外,還監(jiān)聽(tīng)了回車(chē)打開(kāi)標(biāo)簽頁(yè)和切換結(jié)果選中項(xiàng),主要用了keymaster
其api可以參考這里:keymaster官網(wǎng)
主要的代碼:
key.filter = function(event) { var tagName; tagName = (event.target || event.srcElement).tagName; return !(tagName === "SELECT" || tagName === "TEXTAREA"); }; key("down, up", function(e, h) { if (($current_mark != null) && $view.children().length > 1) { switch (h.shortcut) { case "down": if ($current_mark.index() !== bmarks_per_page - 1 && $current_mark.index() < $view.children().length - 1) { return $current_mark = $current_mark.removeClass("current") .next("li") .addClass("current"); } break; case "up": if ($current_mark.index() !== 0) { return $current_mark = $current_mark.removeClass("current") .prev("li") .addClass("current"); } } } }); key("enter, shift + enter", function(e, h) { switch (h.shortcut) { case "enter": case "shift+enter": if ($current_mark != null) { return chrome.tabs.create({ url: $current_mark.find("a").prop("href"), pinned: key.shift ? true : false }); } else { if (pattern.length > 2) { return chrome.tabs.create({ url: "http://www.google.com/search?q=" + pattern }); } } } });
至此,holmes的主要邏輯也就解讀完畢了, 對(duì)于樣式那塊,本文不做解讀,可看出,其實(shí)該擴(kuò)展程序,還有很多優(yōu)化空間,感興趣,其實(shí)可以自己改改,來(lái)優(yōu)化使用體驗(yàn),比如:代碼的一些重復(fù)邏輯、加入事件代理、搜索結(jié)果顯示體驗(yàn)等等。(目前,這個(gè)擴(kuò)展程序在說(shuō)明上貌似最新一版已經(jīng)是2015年的事了,看來(lái)作者也沒(méi)有繼續(xù)更新的打算了)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/83591.html
摘要:作為一名資深碼農(nóng),結(jié)合身邊一群民工的真實(shí)體驗(yàn),小編有那么一點(diǎn)權(quán)威給各位推薦幾款程序員必備常用的擴(kuò)展插件。插件是一款為谷歌瀏覽器定制的非常強(qiáng)大的一款管理插件。 作為一名資深碼農(nóng),結(jié)合身邊一群IT民工的真實(shí)體驗(yàn),小編有那么一點(diǎn)權(quán)威給各位推薦幾款程序員必備、常用的chrome擴(kuò)展插件。1.Click&Clean下載地址:http://www.cnplugins.com/offi...Clic...
摘要:前端日?qǐng)?bào)精選大前端公共知識(shí)梳理這些知識(shí)你都掌握了嗎以及在項(xiàng)目中的實(shí)踐深入貫徹閉包思想,全面理解閉包形成過(guò)程重溫核心概念和基本用法前端學(xué)習(xí)筆記自定義元素教程阮一峰的網(wǎng)絡(luò)日志中文譯回調(diào)是什么鬼掘金譯年,一個(gè)開(kāi)發(fā)者的好習(xí)慣知乎專(zhuān) 2017-06-23 前端日?qǐng)?bào) 精選 大前端公共知識(shí)梳理:這些知識(shí)你都掌握了嗎?Immutable.js 以及在 react+redux 項(xiàng)目中的實(shí)踐深入貫徹閉包思...
摘要:通過(guò)團(tuán)隊(duì)的全力全策,美團(tuán)外賣(mài)的平均率從千分之三降到了萬(wàn)分之二,最優(yōu)值萬(wàn)一左右率統(tǒng)計(jì)方式次數(shù)。美團(tuán)外賣(mài)自年創(chuàng)建以來(lái),業(yè)務(wù)就以指數(shù)級(jí)的速度發(fā)展。目前美團(tuán)外賣(mài)日完成訂單量已突破萬(wàn),成為美團(tuán)點(diǎn)評(píng)最重要的業(yè)務(wù)之一。 面試中常常問(wèn)到的是Android的性能優(yōu)化以及Crash處理。 今天我們來(lái)學(xué)習(xí)一下啊美團(tuán)App的Crash處理。更多參考《Android性能優(yōu)化:手把手帶你全面實(shí)現(xiàn)內(nèi)存優(yōu)化》 原為地...
閱讀 3091·2021-11-23 09:51
閱讀 1737·2021-10-15 09:39
閱讀 1143·2021-08-03 14:03
閱讀 2987·2019-08-30 15:53
閱讀 3505·2019-08-30 15:52
閱讀 2584·2019-08-29 16:17
閱讀 2921·2019-08-29 16:12
閱讀 1726·2019-08-29 15:26