Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
您2019豬事順利,心想事成。
Tab 切換是種很常見的網頁呈現形式,不管是PC或者H5都會經常看到,今天就為小伙伴們提供多種純CSS Tab 切換的實現方式,同時對比一下那種代碼更方便,更通俗易懂。
3種純CSS方式實現Tab 切換
純CSS實現都面臨2個問題:
1、 如何接收點擊事件?
2、 如何操作相關DOM?
擁有 checked 屬性的表單元素, <input type="radio"> 或者 <input type="checkbox"> 能夠接收到點擊事件。
知識點:
1、 使用 radio 標簽的 :checked 偽類,加上 <label for> 實現純 CSS 捕獲點擊事情
2、 使用了 ~ 選擇符對樣式進行控制
<div class="container"> <input class="nav1" id="li1" type="radio" name="nav"> <input class="nav2" id="li2" type="radio" name="nav"> <ul class='nav'> <li class='active'><label for="li1">tab1</label></li> <li><label for="li2">tab2</label></li> </ul> <div class="content"> <div class="content1 default">tab1 內容:123456</div> <div class="content2">tab2 內容:abcdefgkijkl</div> </div> </div>
添加樣式
.container *{ padding: 0; margin: 0; } .container { position: relative; width: 400px; margin: 50px auto; } .container input { display: none; } .nav { position: relative; overflow: hidden; } .nav li { width: 200px; float: left; text-align: center; background: #ddd; list-style: none; } .nav li label { display: block; width: 200px; line-height: 36px; font-size: 18px; cursor: pointer; } .content { position: relative; overflow: hidden; width: 400px; height: 100px; border: 1px solid #999; box-sizing: border-box; padding: 10px; } .content1, .content2 { display: none; width: 100%; height: 100%; } .nav1:checked ~ .nav li { background: #ddd; color: #000; } .nav1:checked ~ .nav li:first-child { background: #ff7300; color: #fff; } .nav2:checked ~ .nav li { background: #ddd; color: #000; } .nav2:checked ~ .nav li:last-child { background: #ff7300; color: #fff; } .nav1:checked ~ .content > div { display: none; } .nav1:checked ~ .content > div:first-child { display: block; } .nav2:checked ~ .content > div { display: none; } .nav2:checked ~ .content > div:last-child { display: block; } .nav li.active { background: #ff7300; color: #fff; } .content .default { display: block; }
知識點:
1、 要使用 :target 偽元素,需要 HTML 錨點,以及錨點對應的 HTML 片段
2、 核心是使用 :target 偽類接收點擊事件
3、 通過兄弟選擇符 ~ 控制樣式
<div class="container"> <div id="content1" class="active">tab 1內容:123456</div> <div id="content2">tab 2內容:abcdefgkijkl</div> <ul class='nav'> <li class="active"><a href="#content1">tab1</a></li> <li><a href="#content2">tab2</a></li> </ul> <div class="wrap"></div> </div>
添加樣式
.container *{ padding: 0; margin: 0; } .container { position: relative; width: 400px; margin: 50px auto; } .nav { position: relative; overflow: hidden; } li { width: 200px; float: left; text-align: center; background: #ddd; list-style: none; } li a { display: block; width: 200px; line-height: 36px; font-size: 18px; cursor: pointer; text-decoration: none; color: #000; } #content1, #content2 { position: absolute; overflow: hidden; top: 36px; width: 400px; height: 100px; border: 1px solid #999; box-sizing: border-box; padding: 10px; } #content1, #content2 { display: none; width: 100%; background: #fff; } #content1:target, #content2:target { display: block; } #content1.active { display: block; } .active ~ .nav li:first-child { background: #ff7300; color: #fff; } #content1:target ~ .nav li { background: #ddd; color: #000; } #content1:target ~ .nav li:first-child { background: #ff7300; color: #fff; } #content2:target ~ .nav li { background: #ddd; color: #000; } #content2:target ~ .nav li:last-child { background: #ff7300; color: #fff; } .wrap { position: absolute; overflow: hidden; top: 36px; width: 400px; height: 100px; border: 1px solid #999; box-sizing: border-box; }
:focus-within 它表示一個元素獲得焦點,或該元素的后代元素獲得焦點。
重點:它或它的后代獲得焦點。
這也就意味著,它或它的后代獲得焦點,都可以觸發 :focus-within。
知識點
1、 這個屬性有點類似 Javascript 的事件冒泡,從可獲焦元素開始一直冒泡到根元素 html,都可以接收觸發 :focus-within 事件
2、 本例子的思路就是通過獲焦態來控制其他選擇器,以及最重要的是利用了父級的 :not(:focus-within) 來設置默認樣式
<div class="container"> <div class="nav-box"> <button class="nav1">tab1</button> <button class="nav2">tab2</button> <div class="content-box"> <div class="content1"> content-1 </div> <div class="content2"> content-2 </div> </div> </div> </div>
添加樣式
.container { width: 300px; margin: 50px auto; padding: 10px; boder: 1px solid #ddd; } .nav-box { font-size: 0; } button { width: 150px; height: 40px; box-sizing: border-box; outline: none; background: #fff; border: 1px solid #ddd; font-size: 18px; cursor: pointer; } button:focus-within { color: #fff; background: #ff7300; } .content-box { font-size: 24px; border: 1px solid #ddd; height: 100px; } .content-box div { display: none; } .nav-box:not(:focus-within) .nav1 { color: #fff; background: #ff7300; } .nav-box:not(:focus-within) .content1 { display: block; } .nav1:focus-within ~ .content-box .content1 { display: block; } .nav2:focus-within ~ .content-box .content2 { display: block; }
3種純CSS方式實現Tab 切換
這個效果就很差一些,因為,在tab失去焦點時,就會復原,回到tab1上面,并不推薦這種方式來實現。小編推薦第一種:checked實現方式,更容易理解。
喜歡小編的點擊關注,了解更多知識!
源碼地址和源文件下載請點擊下方“了解更多”
者:中國社會科學院世界經濟與政治研究所副研究員 彭成義
近日,美國《反海外腐敗法》(又譯為《反海外賄賂法》)因《美國陷阱》一書而“名聲大噪”。這部由法國電力巨頭阿爾斯通前高管皮耶魯齊所著的新書,通過講述切身經歷及詳實考證,揭露了美國如何利用其霸權優勢及“長臂管轄”手段打擊美國企業海外競爭對手的秘密。如今,在中美貿易摩擦的大背景下,美國又對我國電信巨擘華為故伎重演,并要求加拿大將正在溫哥華轉機的華為首席財務官孟晚舟進行了扣留。這使得國人對于美國《反海外腐敗法》及霸凌行徑更加關注并引發熱議。由此,有必要深入討論美國《反海外腐敗法》及其濫用情況。
美國《反海外腐敗法》的出臺與演變
美國《反海外腐敗法》的出臺,有一個重要的背景和政治誘因,即1977年“水門事件”。“水門事件”的發生,使美國高官和大企業主管這些傳統上受人尊重的上層階層的誠信度遭到社會質疑。媒體借機掀起揭開黑幕運動,社會各界開始普遍要求加強對政府官員和大企業行為的監督,官方被迫啟動相關調查。隨之,美國證券交易委員會一份報告披露,美國有400多家公司在海外存在非法或者問題交易,引發社會震動。這直接導致美國國會當年便以絕對優勢通過《反海外腐敗法》,旨在打擊美國企業在國外賄賂行為,重建公眾對于美國商業系統的信心。
《反海外腐敗法》早期的實施效果并不理想,因為它客觀上削弱了美國公司在海外市場的競爭力,遭到美國企業界一定程度的抵制,尤其是那些原本可以把行賄支出計入商業成本而獲得稅收優惠的公司,對此更是怨聲載道。由此,美國分別于1988、1994、1998年三次對《反海外腐敗法》進行修訂,以更適應國際市場的現實情況,同時大力推進《反海外腐敗法》的國際化。具體而言,修改后的《反海外腐敗法》主要有幾個變化。
第一,對國際商業中的一些費用,比如用以促進外國政府機構加快履行日常政府活動的小額支出即“潤滑費”,進行了合法化處理。
第二,擴大了該法的適用對象,從先前的美國公司和個人,擴展到和美國有一定關系的外國企業、自然人或者母公司等。只要在美國上市、使用美元結算,或者僅僅通過設在美國的服務器(如谷歌郵箱或微軟郵箱)收發、存儲(甚至只是過境)電子郵件促成腐敗行為發生,這些都被視為利用了美國的國際貿易工具而被納入該法適用范圍。
第三,要求美國總統采取行動,促成其他國家出臺與《反海外腐敗法》類似的法律。同時,在美國霸權的極力推動下,《反海外腐敗法》國際化取得了重要進展。加拿大一些國家就出臺類似《反海外腐敗法》的國內法。經濟合作與發展組織(OECD)則也于1997年頒布《國際商業交易活動反對行賄外國公職人員公約》。
腐敗是阻礙人類社會發展的一大毒瘤。特別是在當今全球深度一體化的背景下,沒有國家能夠獨善其身,必須團結起來共同致力于反腐。《反海外腐敗法》本是美國單方面的國際反腐行動,但鑒于美國在世界體系中的重要地位,其影響逐漸擴大,在一定程度上推動全球反腐實現了從無到有,并逐漸演變成一個全球腐敗治理機制。
當然,我們也必須認識到,美國制定該法律并在國際層面積極推廣之,并非全然出于反腐倡廉的道德境界,還有為與蘇聯爭霸謀求道德高地的戰略考量。換言之,美國“高尚”行為背后也摻雜著與蘇聯爭霸的私心雜念。而這也為蘇聯解體后,美國濫用《反海外腐敗法》為其私利服務留下了伏筆。
美國《反海外腐敗法》被霸權濫用
近年來,美國《反海外腐敗法》越來越被霸權濫用。首先,雖然民粹主義可以利用反腐旗號上臺,卻并非真心反腐,反而往往使腐敗形勢更加惡化。比如,印度的第一個反腐敗政黨“普通人黨”,在2015年新德里的地方選舉中異軍突起,一舉拿下70個立法會議席中的67個。但是好景不長,很快該黨就因為內斗、骯臟政治以及機制失調,而導致公眾倍感失望。意大利的著名右翼民粹主義政黨也因卷入腐敗丑聞而遭受沉重打擊,導致該黨在2017年的中期選舉中丟掉主要大城市的執政權。法國最大的民粹主義政黨——國民陣線的主席小勒龐,也因讓其保鏢及助理等非歐洲議會工作人員在歐洲議會領“空餉”,而被法國司法機關立案調查,并有10余名“國民陣線”議員涉入此案。
其次,美國總統特朗普本身已成為廉政高風險的重點監視對象,其反腐舉措更多的是一種“美國優先”的手段。作為民粹主義興起的代表,特朗普雖然藉著反腐的緣由上臺,在競選期間也反復發出要抽干華盛頓腐敗沼澤的豪言壯語,但是其許多舉措似乎正在開反腐的倒車。而且,特朗普也因其巨大的商業帝國背景和聯系,成為廉政高風險的重點監視對象。國外在這方面的討論很多,甚至有的民間組織還每月發布特朗普腐敗風險監督報告,梳理分析所有可能指控特朗普涉嫌腐敗的法律條款等。
不少人認為,特朗普總統及其行政當局某些做法不僅不合乎倫理,而且存在違法行為。特朗普就職不久,華盛頓的一家非盈利組織——“責任與倫理公民”,就正式向地方法院提起了針對特朗普的訴訟,控告特朗普違反了美國憲法中規定的“外國收益條款”。2017年6月中旬,華盛頓特區總檢察長卡爾·拉辛及馬里蘭州總檢察長布萊恩·弗洛西也對特朗普提起訴訟,指控他存在“史無前例的違憲行為”。該訴訟還宣稱,特朗普所繼續擁有的一個全球性的商業帝國已使總統“深深的陷入一個由國外及國內政府行動者組成的集團中”,并且破壞了美國的政治體系的廉潔性。
早在2012年,特朗普就公開抨擊《反海外腐敗法》為“荒謬和糟糕的法律”。不少觀察家擔心特朗普會削弱《反海外腐敗法》。事實上,特朗普和共和黨領導的國會已經放棄奧巴馬政府在打擊石油和天然氣行業反賄賂的努力,美國內務部最近也采取行動停止了對《采掘業透明倡議》的執行。美國退出TPP也被不少人認為是美國反腐的倒退和損失,因為其中有專門的透明與反腐條款將反腐與貿易聯系起來,而這耗掉了不少廉政工作者的努力和心血。而且,更令人擔憂的是,特朗普的腐敗表象以及抵制防止利益沖突舉措的態度極可能為國內的其他腐敗官員所效仿。
總之,不管是在美國國內還是國外,美國政府過去幾十年苦心經營起來的廉潔領袖形象似乎在特朗普當選后短暫的時間里出現了快速的崩塌。開反腐倒車的特朗普政府,無疑已經使以廉潔模范自居的美國開始成為反腐的笑柄。當然,這對全球反腐事業也構成一定的沖擊。
然而,就是這樣一位對反腐不屑一顧的總統,卻在其任上開始大肆啟動對外國企業涉嫌賄賂的處罰,力度之大、金額之高令人訝然。這從下圖2016-2018年的黃色部分所代表的對外處罰金額就可見一斑。
圖1:美國通過《反海外腐敗法》對企業實體的處罰一覽(圖表引自http://fcpa.stanford.edu/statistics-analytics.html?tab=2,2019年6月9日訪問)
啟示
第一,我們應該客觀看待美國《反海外腐敗法》的歷史功績。不容否認,美國制定和推廣該法對于形成今天全球腐敗治理有著重要的推動作用。打造全球廉潔的從商環境無疑仍然具有感召力,并應成為世界各國共同努力的目標。
第二,對于美國利用其霸權優勢及長臂管轄手段打擊國外競爭企業應該引起世人的高度重視和清醒認識。事實上,不僅是在利用《反海外腐敗法》方面,當前特朗普政府的“美國優先”戰略正在將其過去幾十年辛辛苦苦營造的秩序和制度所葬送。
第三,中國或可扛起促進全球腐敗治理的大旗。一方面注重發揮《反海外腐敗法》對于國際治理的積極促進作用,另一方面帶動全球堅決抵制其被某些霸權私用濫用。這對于進一步提升我國在全球舞臺的形象,提高中國智慧和中國方案的感召力,并維護世界的公平與正義,都有重要的意義。
本文主要的內容是幫助讀者朋友梳理chrome插件的tabs能力,如果您是第一次閱讀本文,也建議您在閱讀完本文后,嘗試看看我下面的這些系列文章,它們可以更好的幫您認識和了解chrome插件:
一款瀏覽器插件具備非常強大的能力,它不僅可以向當前所有的站點里注入腳本,對網站的功能進行擴展。更重要的是它還可以和瀏覽器的標簽系統進行交互,從而創建、修改、管理每一個tab,而這一切都基于插件系統為我們提供的tabs相關的API,chrome不僅提供了我們用于操作和管理tabs的API,而且還提供了和content腳本之間的通信方法。
溫馨提示:
Tabs API 只能在background腳本中以及option腳本、popup腳本、由chrome創建的tab中訪問到,在content腳本中是無法訪使用的。
換句話說,chrome有選擇性的給不同的腳本環境注入了不同的chrome對象,導致提供的API具備差異性。
該圖是我們在特定環境下可以通過chrome.tabs訪問的所有的api,這些就是chrome為我們內置的提供給開發者的能力
在之前的文章中我們提到過,如果要使用某些特別的API,我們需要在插件配置文件manifest.json中配置相應的權限聲明,但幸運的是對于tabs相關的部分API不需要在manifest.json中顯式的配置“tabs”就可以直接使用。比如說: 創建一個新的tab,重新加載某個tab,或者導航到另外一個URL等等。
但是下面的這些API在使用的時候,則需要加上相關的配置才可以使用,比如說:
chrome.tabs.executeScript() // 注入一段腳本并執行
chrome.tabs.insertCss() // 注入一段css樣式
chrome.tabs.removeCss() // 移除一段css樣式
{
// manifest.json "host_permissions":[ "<all_urls>" ] // 支持正則匹配正則
}
接下來我們一一通過案例來認識他們,從而感受每一個API的具體行為以及他們的使用條件、注意事項等等。
我們可以通過這個API來創建一個新的tab,這個tab和普通的站點不一樣,屬于插件所屬的頁面,因此支持跨域請求、獲取更多的chrome提供的方法。
// background.js
chrome.runtime.onInstalled.addListener(({reason})=> {
if (reason==='install') {
chrome.tabs.create({
url: "newtab.html" // 相對于background腳本的路徑下需要有一個newtab.html文件
});
}
});
上面的腳本意味著在插件第一次安裝完成之后,就會立馬創建一個新的標簽頁,所以如果我們想要在任何時候創建一個新的tab,就可以使用這個API,行業內很多插件的工作臺都是創建一個新的tab頁進行工作的,比如著名的代理插件SwitchySharp
該api默認支持,不需要額外的manifest配置
我們可能有這樣的需要,獲取當前瀏覽器窗口處于激活狀態的tab頁面,因為對于同一個窗口,有且只有會一個tab是展示在用戶面前的,我們把這樣的tab稱為激活狀態,這個時候我們就需要用到下面的api。
async function getCurrentTab() { let queryOptions={ active: true }; let [tab]=await chrome.tabs.query(queryOptions); return tab; }
調用上面的方法,你就可以獲得當前窗口激活的那個tab的實例對象了,從這個對象中,你可以獲取到對應的tab唯一的id、url、圖標等信息。
值得注意的是,如果chrome瀏覽器打開了多個窗口,就意味著可能每一個窗口都會存在一個激活的tab,因此我們獲取的tab就會是多個,這個時候如果只是解構出第一個可能是不夠嚴謹的。
因此我們可以通過添加搜索條件來精確的查找:
async function getCurrentTab() {
let queryOptions={
active: true , currentWindow:true
};
let [tab]=await
chrome.tabs.query(queryOptions);
return tab;
}
通過添加一個參數currentWindow,意味著只搜索腳本運行所在窗口的激活的tab,這個時候肯定只會查找出唯一的一個tab,解構第一個就不會有問題。
搜索條件除了上述之外,還有下面可以選擇:
參數 | 類型 | 作用 |
active | boolean | 是否處于激活狀態 |
audible | boolean | 是否處于播放音頻狀態 |
currentWindow | boolean | 是否處于腳本所在窗口內 |
groupId | number | 是否處于某個分組內 |
highlighted | boolean | 是否處于高亮狀態 |
index | number | 窗口從左往右第index個tab |
pinned | boolean | 是否處于被固定的狀態 |
status | unloaded/loading/complete | 匹配tab的status為該status的tabs |
title | string | 匹配tab的title為該title的tabs |
url | string | 匹配tab的url為該url的tabs |
windowId | number | 特定窗口下的tabs |
windowType | normal/popup/panel/app/devtools | 特定的窗口類型下所在的tabs |
被固定是指那些通過右鍵點擊tab的時候,選擇固定在最左側的標簽,并且可以固定多個。
該api默認支持,需要額外的manifest配置,需要顯式聲明“tabs”的permissions
我們可以很方便的給指定的tab發送消息,一般來說我們可以在content腳本中做消息的監聽,接收到消息后使其執行不同的業務邏輯。
chrome.tabs.sendMessage(
tabId: number, // 目標tab的id
message: any, // 發送信息
options?: object, // 其他配置項
callback?: function, // 回調函數 )
上面這個是V3版本的插件使用的,在V2版本中我們使用chrome.tabs.sendRquest()
// 在v3版本中已廢棄
chrome.tabs.sendRequest(
tabId: number, // 目標tab的id
request: any, // 發送信息
callback?: function, // 回調函數
)
如果我們希望修改一個tab的一些參數信息,我們可以選擇使用下面這個API:
chrome.tabs.update( tabId?: number, updateProperties: object, callback?: function, )
其中updateProperties的值就是上面提到的queryOptions的屬性保持一致,例如我們可以動態的更改指定tab的title、url、pinned等狀態屬性!
當我們按住ctrl的同時再滑動鼠標滾輪的話就可以調整頁面的縮放比例,這個可能大家平時都深有體會,但是實際上這個也可以通過插件給我們提供的API來動態的進行調整:
chrome.tabs.setZoom( tabId?: number, zoomFactor: number, // 縮放比例 callback?: function, )
我們介紹的第一個API就展示了如何創建一個新的tab,他會默認創建在最末尾,也就是最右側,如果這個放置位置我們不滿意,我們也可以將其放置在我們想要的位置。
移動
chrome.tabs.move(
tabIds: number | number[],
moveProperties: object,
callback?: function,
)
type moveProperties={ index?:number, // 想要移動至的index索引位置. `-1` 移動至窗口末尾.
windowId?:number // 移動至的窗口id
}
移除
chrome.tabs.remove( tabIds: number | number[], callback?: function, )
刷新
chrome.tabs.reload( tabId?: number, reloadProperties?: object, callback?: function, ) type reloadProperties={ bypassCache?:boolean // 是否繞過本地緩存 默認不繞過,也就是使用本地緩存。 }
我們可以通過插件來控制一個tab的前進后退(如果他們都曾有過跳轉的記錄)
chrome.tabs.goBack( // 回到最近的一次歷史記錄 tabId?: number, callback?: function, ) chrome.tabs.goForward( // 去到下一個歷史記錄,如果有的話 tabId?: number, callback?: function, )
當我們的tab開的特別多的時候,瀏覽器會有個小優化,對于某些長時間不用的tab,瀏覽器會清空內存中對其的狀態存貯,因此當我們再次將其激活時會重新加載!這個過程插件也提供了API可以幫助我們做到:
chrome.tabs.discard( tabId?: number, callback?: function, ) chrome.tabs.duplicate( // 這個API與discard相反,可以幫助我們復制一個一摸一樣的tab標簽 tabId: number, callback?: function, )
如果我們希望將某些具備相似特征的網站分成一個組,使其能夠在視圖上更好的被察覺,那么我們就可以通過插件為我們提供的API來進行實現:
第一步:篩選出希望分到同一組的tabs
const tabs=await chrome.tabs.query({ url: [ "https://developer.chrome.com/*"], });
根據前面的知識,我們很容易就可以知道tabs就是域名為 "developer.chrome.com" 開頭的所有站點的tab集合;
第二步:將他們分為一組
const tabIds=tabs.map(({ id })=> id); const group=await chrome.tabs.group({ tabIds });
上圖中就可以看到所有符合條件的站點就被分為同一個組了,這個API的使用方式是:
chrome.tabs.group( options: GroupOptions, callback?: function, ) type GroupOptions={ tabIds?:number[], // 希望被分組的tab的id的集合 groupId?:number, // 已有的分組 createProperties?:{ windowId?:number // 希望分組被創建在那個窗口, 默認是腳本所在窗口 } }
額外的話:
如果我們希望在分組上再加上一個樣式或者字樣作為標記的話,也可以這樣做:
// 第一步: 在manifest.json中添加“tabGrpups”的權限 { ... "permissions":[ "tabGroups" ] } //第二步: chrome.tabGroups.update(group, { title: "這是分組1" , color:'red' });
就可以修改這個分組的一些特征,上面是增加了一個標題,效果如下:
以上我們介紹了基本的API,接下來我們通過一些案例來實際感受一下每個API的作用:
準備以下的項目:
manifest.json
{
"name": "tabs demo",
"description": "tabs demo",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_icon":
{
"16": "/images/get_started16.png",
"32": "/images/get_started32.png",
"48": "/images/get_started48.png",
"128": "/images/get_started128.png"
}
},
"content_scripts": [
{
"js": ["content.js"],
"matches": ["<all_urls>"] } ],
"background":
{
"service_worker": "background.js"
},
"icons": {
"16": "/images/get_started16.png",
"32": "/images/get_started32.png",
"48": "/images/get_started48.png",
"128": "/images/get_started128.png"
},
"permissions": ["tabs", "tabGroups"] }
content.js / background.js
// content.js let color=""; console.log("content.js"); chrome.runtime.onMessage.addListener((message, sender, sendResponse)=> { color=document.body.style.color; document.body.style.background=message; sendResponse("changed"); }); // background.js console.log(chrome);
newtab.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>chrome插件</title> </head> <body> <h1>我是一個由chrome插件創建的頁面</h1> </body> </html>
popup.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <section> <h1>創建新的頁面</h1> <button id="create-tab">創建</button> </section> <section> <h1>查找符合條件的tab</h1> <div> <span>是否激活</span> <span>是</span> <input type="radio" name="isActive" value="1" /> <span>否</span> <input type="radio" name="isActive" value="0" /> </div> <div> <span>是否屬于當前窗口:</span> <span>是</span> <input type="radio" name="isCurrentWindow" value="1" /> <span>否</span> <input type="radio" name="isCurrentWindow" value="0" /> </div> <div> <span>url(支持正則):</span> <input type="text" id="url" /> </div> <div> <span>title</span> <input type="text" id="title" /> </div> <div> <span>index</span> <input type="text" id="index" /> </div> <div> <span>是否被固定</span> <span>是</span> <input type="radio" name="pinned" value="1" /> <span>否</span> <input type="radio" name="pinned" value="0" /> </div> <div> <span>status</span> <select name="status" id="status"> <option value="unloaded">unloaded</option> <option value="loading">unloaded</option> <option value="complete">unloaded</option> </select> </div> <button id="query-tab">查找</button> <div> <div>查找結果:</div> <div id="search-result"></div> </div> </section> <section> <h1>發送消息</h1> <input type="color" id="send-value" /> <button id="send-btn">變色吧</button> </section> <section> <h1>刪/改/移/丟棄/復制</h1> <div> <input type="text" id="move-index" /> <button id="move">移動當前的tab</button> </div> <div> <button id="remove">移除當前的tab</button> </div> <div> <button id="reload">刷新當前的tab</button> </div> <div> <input type="text" id="discard-value" /> <button id="discard">丟棄</button> </div> <div> <button id="duplicate">復制</button> </div> <div> <input type="text" id="update-value" /> <button id="update">更新</button> </div> </section> <section> <h1>縮放比</h1> <div> <input type="text" id="zoom" /> <button id="zoom-btn">調整</button> </div> </section> <section> <h1>分組</h1> <div> <input type="text" id="group-title" /> <button id="group">使用查詢的結果進行分組</button> </div> </section> <section> <h1>導航</h1> <div> <button id="goForward">前進</button> <button id="goBack">前進</button> </div> </section> <script src="./popup.js"></script> </body> </html>
popup.js
document.getElementById("create-tab").addEventListener("click", ()=> { chrome.tabs.create({ url: "newtab.html", // 相對于background腳本的路徑下需要有一個newtab.html文件 }); }); let Tabs=[]; const getSelect=(list)=> { const yes=list[0]; const no=list[1]; if (yes.checked) { return yes.defaultValue==="1"; } if (no.checked) { return no.defaultValue==="1"; } return false; }; document.getElementById("query-tab").addEventListener("click", async ()=> { const active=getSelect(document.getElementsByName("isActive")); const currentWindow=getSelect( document.getElementsByName("isCurrentWindow") ); const pinned=getSelect(document.getElementsByName("pinned")); const url=document.getElementById("url").value; const title=document.getElementById("title").value; const index=document.getElementById("index").value; const queryOptions={ active, currentWindow, pinned, }; if (url) { queryOptions.url=url; } if (title) { queryOptions.title=title; } if (index) { queryOptions.index=index - 0; } console.log(queryOptions); const tabs=await chrome.tabs.query(queryOptions); document.getElementById("search-result").innerHTML=JSON.stringify( tabs.map(({ id })=> ({ id })) ); Tabs=tabs; }); document.getElementById("send-btn").addEventListener("click", async ()=> { const color=document.getElementById("send-value").value; const [tab]=await chrome.tabs.query({ active: true, currentWindow: true }); const response=await chrome.tabs.sendMessage(tab.id, color); console.log(color, response); }); const getCurrentTab=async ()=> { const [tab]=await chrome.tabs.query({ active: true, currentWindow: true }); return tab.id; }; document.getElementById("move").addEventListener("click", async ()=> { const index=document.getElementById("move-index").value - 0; const tabIds=await getCurrentTab(); chrome.tabs.move(tabIds, { index }); }); document.getElementById("remove").addEventListener("click", async ()=> { const tabIds=await getCurrentTab(); chrome.tabs.remove(tabIds); }); document.getElementById("reload").addEventListener("click", async ()=> { const tabId=await getCurrentTab(); chrome.tabs.reload(tabId); }); document.getElementById("discard").addEventListener("click", async ()=> { const tabId=document.getElementById("discard-value").value - 0; chrome.tabs.discard(tabId); }); document.getElementById("duplicate").addEventListener("click", async ()=> { const tabId=await getCurrentTab(); chrome.tabs.duplicate(tabId); }); document.getElementById("zoom-btn").addEventListener("click", async ()=> { const tabId=await getCurrentTab(); const zoomFactor=document.getElementById("zoom").value - 0; chrome.tabs.setZoom(tabId, zoomFactor); }); document.getElementById("group").addEventListener("click", async ()=> { const tabIds=Tabs.map(({ id })=> id); const title=document.getElementById("group-title").value; const group=await chrome.tabs.group({ tabIds }); chrome.tabGroups.update(group, { color: "red", title }); }); document.getElementById("goForward").addEventListener("click", async ()=> { const tabId=await getCurrentTab(); chrome.tabs.goForward(tabId); }); document.getElementById("goBack").addEventListener("click", async ()=> { const tabId=await getCurrentTab(); chrome.tabs.goBack(tabId); });
以上的資源我會放到github上,大家可以download下來直接在自己的瀏覽器上運行,查看效果,也希望有收獲后給不吝star哈!。
下面是我本地的測試效果:
創建頁面/發送消息
查詢
刪/改/更新
分組
有了以上的武器,就可以玩轉tabs啦!一起開始開發chrome插件吧!
以下是我的其他文章,歡迎閱讀
保姆級講解JS精度丟失問題(圖文結合)
shell、bash、zsh、powershell、gitbash、cmd這些到底都是啥?
從0到1開發一個瀏覽器插件(通俗易懂)
用零碎時間個人建站(200+贊)
另外我有一個自己的網站,歡迎來看看 new-story.cn
創作不易,如果您覺得文章有任何幫助到您的地方,或者觸碰到了自己的知識盲區,請幫我點贊收藏一下,或者關注我,我會產出更多高質量文章,最后感謝您的閱讀,祝愿大家越來越好。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。