Greasemonkey歷險(xiǎn)記之荔枝FM

從13年開始我迷上了podcast辟拷,尤其是在夜晚一片寂靜的時(shí)候只磷,邊聽podcast邊寫代碼或是看書學(xué)習(xí)真是一種難以言喻的幸福庆杜。最早的時(shí)候是去新浪播客收聽的简软,可那蛋疼的速度和糟糕的設(shè)計(jì)蛮拔,讓我很快就轉(zhuǎn)向荔枝FM了。荔枝的速度在法國挺快痹升,中文播客也比較全建炫。我平時(shí)收聽的主要渠道是web端,荔枝的設(shè)計(jì)雖然簡單疼蛾,但也到清爽干凈肛跌,比起它日漸復(fù)雜的移動(dòng)端更得我心。但是荔枝FM主打的畢竟是移動(dòng)端察郁,web端一直都非常簡陋衍慎。最讓我不爽的是web端至今都沒能實(shí)現(xiàn)訂閱自選電臺這個(gè)最簡單,也最核心的功能皮钠。

既然官方等不到了稳捆,那就自己來弄一個(gè)吧。上一篇介紹過Greasemonkey和類似查件的作用了鳞芙,他們可以在訪問指定頁面的時(shí)候執(zhí)行預(yù)先寫好的腳本眷柔,以此實(shí)現(xiàn)自定義頁面。在這里原朝,我需要的是一個(gè)簡單的功能:在web端的左邊菜單欄中增加一個(gè)按鈕驯嘱,用來展開自選電臺列表。

有了功能需要喳坠,讓我們考慮一下實(shí)現(xiàn)思路吧鞠评。Dev tools和Inspect element是我們手中的利器, 很快我就發(fā)現(xiàn)一個(gè)有趣的事實(shí):該網(wǎng)站是基于angular實(shí)現(xiàn)的壕鹉!它帶有SPA的特點(diǎn)剃幌,當(dāng)我們點(diǎn)擊左邊菜單欄按鈕的時(shí)候,只有中間的內(nèi)容區(qū)會刷新晾浴。左邊的菜單欄和右邊的播放器是基本不刷新的负乡。這對我們要實(shí)現(xiàn)的功能來說真是太棒了!自選電臺的腳本只在頁面第一次加載的時(shí)候注入DOM脊凰,每次更換電臺的時(shí)候只有中間的電臺信息部分刷新抖棘,該腳本不會再次執(zhí)行,開銷小多了!

好了切省,那就開始動(dòng)手吧最岗。首先自然是怎么確定自選電臺了;觀察幾次就會發(fā)現(xiàn)朝捆,每個(gè)電臺都由唯一的數(shù)字代表般渡,只要將這個(gè)數(shù)字加到網(wǎng)址后面就可以跳轉(zhuǎn)到該電臺了。比如Gadio的地址是http://www.lizhi.fm/#/29345芙盘,友的聊的地址是http://www.lizhi.fm/#/14393/驯用。這就簡單多了,只要保存每個(gè)電臺的唯一地址就可以了:

var myRadioList = {  
  gadio: '[http://www.lizhi.fm/#/29345'](http://www.lizhi.fm/#/29345'),  
  友的聊: '[http://www.lizhi.fm/#/14393'](http://www.lizhi.fm/#/14393'), 
   二次元: '[http://www.lizhi.fm/#/22557'](http://www.lizhi.fm/#/22557'),  
  糖蒜廣播: '[http://www.lizhi.fm/#/13461'](http://www.lizhi.fm/#/13461') 
};

好吧何陆,這種定義方式實(shí)在太不靈活了晨汹。不過作為第一版的腳本豹储,從簡單的贷盲,可實(shí)現(xiàn)的方案開始并無不可,日后再迭代就是了剥扣。電臺列表有了巩剖,下面就該在左邊加個(gè)按鈕了。用inspect element找到左邊導(dǎo)航欄的位置:

var ul = document.querySelector('.wrap > .leftNav > .content > ul');

然后就該生成一個(gè)按鈕加到ul上了:

var radioButton = document.createElement('button'); 
radioButton.class = 'my-radio'; 
radioButton.style.cssText = "margin:3px 3px 3px 15px"; 
var b = document.createElement('b'); 
b.innerHTML = '自選電臺'; radioButton.appendChild(b);
ul.appendChild(radioButton);

我知道這種inline css很丑钠怯,但作為一個(gè)簡單小腳本佳魔,你們就原諒我的放蕩不羈吧……

好了,按鈕有了晦炊。下面該生成列表鞠鲜,并在按鈕上綁定點(diǎn)擊事件來展開列表了。綁定事件很簡單:

radioButton.onclick = toggleRadioList;

toggleRadioList就是響應(yīng)點(diǎn)擊事件的方法断国,由該方法來展開和收起列表贤姆。得先有列表才行啊,鑒于列表本質(zhì)上就是ul元素稳衬,我們先創(chuàng)建一個(gè)ul節(jié)點(diǎn):

var radioList = document.createElement('ul'); 
radioList.className = 'radio-list';
radioList.style.cssText = "list-style-type:none;margin:3px;padding:0px 15px;visibility:hidden";

為了方便toggle函數(shù)改變它的狀態(tài)霞捡,特地加上了一個(gè)class來方便查找。好了薄疚,下面就該按定義的電臺對象一次生成內(nèi)部的li節(jié)點(diǎn)了:

var frag = document.createDocumentFragment();
Object.keys(itemList).forEach(function(key) {  
  var li = document.createElement('li');  
  var a = document.createElement('a');  
  a.href = itemList[key];  
  a.innerHTML = key;  
  a.style.cssText = "text-decoration:underline";
  li.appendChild(a);  frag.appendChild(li);
 });
radioList.appendChild(frag);
target.appendChild(radioList);

注意這里我用了一個(gè)fragment來添加li節(jié)點(diǎn)碧信。其實(shí)這里并不是必須的,但從練習(xí)的角度來看街夭,這么寫是符合性能實(shí)踐的砰碴。我們都知道DOM操作開銷是非常高的,每次DOM變動(dòng)都會使瀏覽器重新計(jì)生成DOM樹板丽,然后重新渲染DOM呈枉。從性能的角度來看,DOM操作的次數(shù)越少越好。于是先用一個(gè)fragment來添加li節(jié)點(diǎn)碴卧,最后再將該fragment注入DOM中弱卡。這樣我們只用一次DOM操作就注入了所有的li節(jié)點(diǎn),比每生成一個(gè)li就注入要高效的多住册,隨著列表的增長婶博,性能方面的差距會越來越大。但我們這里的radioList直到最后才加入DOM荧飞,所以問題要小一些凡人,但無論如何,記得這一點(diǎn)對以后會有幫助的叹阔。

最后只剩下響應(yīng)點(diǎn)擊事件的toggleRadioList函數(shù)了挠轴。這個(gè)函數(shù)的作用就是找到class為radio-list的列表,如果該列表已經(jīng)可見了就隱藏它耳幢,否則就顯示它:

function toggleRadioList() {  
  var list = document.querySelector('.radio-list');  
  if (list.style.visibility === 'hidden')  
    list.style.visibility = 'visible';  
  else  
    list.style.visibility = 'hidden';
 }

好了岸晦,零件都齊活了,腳本應(yīng)該可以用了吧睛藻?等等启上,我最近剛想起來一個(gè)問題:全局命名空間的沖突。大家都直到上個(gè)leanpub的腳本店印,所有函數(shù)是直接暴露在global下的冈在。這會有什么問題呢?可能會出現(xiàn)變量沖突按摘!比如我這有一個(gè)toggleRadioList變量包券,如果荔枝網(wǎng)站本身有一個(gè)同名變量,沖突就出現(xiàn)了炫贤,荔枝網(wǎng)站的某部分功能也就會出現(xiàn)問題了溅固。為了確保沖突不出現(xiàn),我們需要將我們自己定義的腳本限制在一個(gè)命名空間內(nèi)照激,不要直接暴露出來发魄。最適合完成這個(gè)任務(wù)的自然就是IIF了,詳情我在去年的一篇文卓中已有講解俩垃,就不再詳述了励幼。簡單來說,就是將我們所有的腳本都包含在這樣一個(gè)函數(shù)中:

(function() { 
  //自定義腳本內(nèi)容
})()

基于JS函數(shù)作用域定義口柳,里面包含的所有變量和函數(shù)定義都只在該函數(shù)內(nèi)部可見苹粟,實(shí)現(xiàn)了和global的隔離。

DeepinScreenshot20150501000457.png

到這里跃闹,腳本就差不多了嵌削。還有很多可以改進(jìn)的地方毛好,比如可以增加一個(gè)輸入框讓用戶自己輸入電臺地址,然后保存到localStorage中苛秕;改進(jìn)一下CSS讓電臺列表的顯示更清晰肌访。這些東西以后再慢慢來吧,已經(jīng)快要午夜了艇劫,讓我們選一個(gè)podcast吼驶,從陌生人的聲音中取得一絲慰藉吧。

P.S: 完整腳本地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末店煞,一起剝皮案震驚了整個(gè)濱河市蟹演,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌顷蟀,老刑警劉巖酒请,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鸣个,居然都是意外死亡羞反,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門毛萌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苟弛,“玉大人喝滞,你說我怎么就攤上這事阁将。” “怎么了右遭?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵做盅,是天一觀的道長。 經(jīng)常有香客問我窘哈,道長吹榴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任滚婉,我火速辦了婚禮图筹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘让腹。我一直安慰自己远剩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布骇窍。 她就那樣靜靜地躺著瓜晤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腹纳。 梳的紋絲不亂的頭發(fā)上痢掠,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天驱犹,我揣著相機(jī)與錄音,去河邊找鬼足画。 笑死雄驹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淹辞。 我是一名探鬼主播荠医,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼桑涎!你這毒婦竟也來了彬向?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤攻冷,失蹤者是張志新(化名)和其女友劉穎娃胆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體等曼,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡里烦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禁谦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胁黑。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖州泊,靈堂內(nèi)的尸體忽然破棺而出丧蘸,到底是詐尸還是另有隱情,我是刑警寧澤遥皂,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布力喷,位于F島的核電站,受9級特大地震影響演训,放射性物質(zhì)發(fā)生泄漏弟孟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一样悟、第九天 我趴在偏房一處隱蔽的房頂上張望拂募。 院中可真熱鬧,春花似錦窟她、人聲如沸陈症。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爬凑。三九已至,卻和暖如春试伙,著一層夾襖步出監(jiān)牢的瞬間嘁信,已是汗流浹背于样。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留潘靖,地道東北人穿剖。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像卦溢,于是被迫代替她去往敵國和親糊余。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,742評論 25 707
  • 第一部分 準(zhǔn)入訓(xùn)練 第1章 進(jìn)入忍者世界 js開發(fā)人員通常使用js庫來實(shí)現(xiàn)通用和可重用的功能单寂。這些庫需要簡單易用贬芥,...
    如201608閱讀 1,343評論 1 2
  • 1.JQuery 基礎(chǔ) 改變web開發(fā)人員創(chuàng)造搞交互性界面的方式。設(shè)計(jì)者無需花費(fèi)時(shí)間糾纏JS復(fù)雜的高級特性宣决。 1....
    LaBaby_閱讀 1,330評論 0 2
  • 房間里空蕩的竟毫無生氣也似得 而敘舊竟只夠吃倆杯茶 未湊滿的情誼 晚安來填補(bǔ) 太多的遺憾與失落
    我們的愛人笛安閱讀 224評論 0 0
  • 接孩子放學(xué)回家尊沸,繞道印象風(fēng)陵威沫,今天突然想和孩子玩一圈再回。 玩夠了洼专,天黑了棒掠,來到摩托車前準(zhǔn)備回家,才發(fā)現(xiàn)車鑰匙不見...
    張新樂閱讀 135評論 0 0