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 国产靠逼视频,日韩高清在线,大陆一级毛片免费视频观看

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          N種純CSS花樣實(shí)現(xiàn)Tab 切換

          N種純CSS花樣實(shí)現(xiàn)Tab 切換

          您2019豬事順利,心想事成。

          前言

          Tab 切換是種很常見(jiàn)的網(wǎng)頁(yè)呈現(xiàn)形式,不管是PC或者H5都會(huì)經(jīng)常看到,今天就為小伙伴們提供多種純CSS Tab 切換的實(shí)現(xiàn)方式,同時(shí)對(duì)比一下那種代碼更方便,更通俗易懂。

          3種純CSS方式實(shí)現(xiàn)Tab 切換

          純CSS實(shí)現(xiàn)都面臨2個(gè)問(wèn)題:

          1、 如何接收點(diǎn)擊事件?

          2、 如何操作相關(guān)DOM?

          checked 偽類實(shí)現(xiàn)純 CSS Tab 切換

          擁有 checked 屬性的表單元素, <input type="radio"> 或者 <input type="checkbox"> 能夠接收到點(diǎn)擊事件。

          知識(shí)點(diǎn):

          1、 使用 radio 標(biāo)簽的 :checked 偽類,加上 <label for> 實(shí)現(xiàn)純 CSS 捕獲點(diǎn)擊事情

          2、 使用了 ~ 選擇符對(duì)樣式進(jìn)行控制

          <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 內(nèi)容:123456</div> 
           <div class="content2">tab2 內(nèi)容: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; 
          }
          

          target 偽類實(shí)現(xiàn)純 CSS Tab 切換

          知識(shí)點(diǎn):

          1、 要使用 :target 偽元素,需要 HTML 錨點(diǎn),以及錨點(diǎn)對(duì)應(yīng)的 HTML 片段

          2、 核心是使用 :target 偽類接收點(diǎn)擊事件

          3、 通過(guò)兄弟選擇符 ~ 控制樣式

          <div class="container"> 
           <div id="content1" class="active">tab 1內(nèi)容:123456</div> 
           <div id="content2">tab 2內(nèi)容: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 來(lái)實(shí)現(xiàn) tab 切換功能

          :focus-within 它表示一個(gè)元素獲得焦點(diǎn),或該元素的后代元素獲得焦點(diǎn)。

          重點(diǎn):它或它的后代獲得焦點(diǎn)。

          這也就意味著,它或它的后代獲得焦點(diǎn),都可以觸發(fā) :focus-within。

          知識(shí)點(diǎn)

          1、 這個(gè)屬性有點(diǎn)類似 Javascript 的事件冒泡,從可獲焦元素開(kāi)始一直冒泡到根元素 html,都可以接收觸發(fā) :focus-within 事件

          2、 本例子的思路就是通過(guò)獲焦態(tài)來(lái)控制其他選擇器,以及最重要的是利用了父級(jí)的 :not(:focus-within) 來(lái)設(shè)置默認(rèn)樣式

          <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方式實(shí)現(xiàn)Tab 切換

          這個(gè)效果就很差一些,因?yàn)椋趖ab失去焦點(diǎn)時(shí),就會(huì)復(fù)原,回到tab1上面,并不推薦這種方式來(lái)實(shí)現(xiàn)。小編推薦第一種:checked實(shí)現(xiàn)方式,更容易理解。

          公告

          喜歡小編的點(diǎn)擊關(guān)注,了解更多知識(shí)!

          源碼地址和源文件下載請(qǐng)點(diǎn)擊下方“了解更多”

          者:中國(guó)社會(huì)科學(xué)院世界經(jīng)濟(jì)與政治研究所副研究員 彭成義

          近日,美國(guó)《反海外腐敗法》(又譯為《反海外賄賂法》)因《美國(guó)陷阱》一書(shū)而“名聲大噪”。這部由法國(guó)電力巨頭阿爾斯通前高管皮耶魯齊所著的新書(shū),通過(guò)講述切身經(jīng)歷及詳實(shí)考證,揭露了美國(guó)如何利用其霸權(quán)優(yōu)勢(shì)及“長(zhǎng)臂管轄”手段打擊美國(guó)企業(yè)海外競(jìng)爭(zhēng)對(duì)手的秘密。如今,在中美貿(mào)易摩擦的大背景下,美國(guó)又對(duì)我國(guó)電信巨擘華為故伎重演,并要求加拿大將正在溫哥華轉(zhuǎn)機(jī)的華為首席財(cái)務(wù)官孟晚舟進(jìn)行了扣留。這使得國(guó)人對(duì)于美國(guó)《反海外腐敗法》及霸凌行徑更加關(guān)注并引發(fā)熱議。由此,有必要深入討論美國(guó)《反海外腐敗法》及其濫用情況。

          美國(guó)《反海外腐敗法》的出臺(tái)與演變

          美國(guó)《反海外腐敗法》的出臺(tái),有一個(gè)重要的背景和政治誘因,即1977年“水門事件”。“水門事件”的發(fā)生,使美國(guó)高官和大企業(yè)主管這些傳統(tǒng)上受人尊重的上層階層的誠(chéng)信度遭到社會(huì)質(zhì)疑。媒體借機(jī)掀起揭開(kāi)黑幕運(yùn)動(dòng),社會(huì)各界開(kāi)始普遍要求加強(qiáng)對(duì)政府官員和大企業(yè)行為的監(jiān)督,官方被迫啟動(dòng)相關(guān)調(diào)查。隨之,美國(guó)證券交易委員會(huì)一份報(bào)告披露,美國(guó)有400多家公司在海外存在非法或者問(wèn)題交易,引發(fā)社會(huì)震動(dòng)。這直接導(dǎo)致美國(guó)國(guó)會(huì)當(dāng)年便以絕對(duì)優(yōu)勢(shì)通過(guò)《反海外腐敗法》,旨在打擊美國(guó)企業(yè)在國(guó)外賄賂行為,重建公眾對(duì)于美國(guó)商業(yè)系統(tǒng)的信心。

          《反海外腐敗法》早期的實(shí)施效果并不理想,因?yàn)樗陀^上削弱了美國(guó)公司在海外市場(chǎng)的競(jìng)爭(zhēng)力,遭到美國(guó)企業(yè)界一定程度的抵制,尤其是那些原本可以把行賄支出計(jì)入商業(yè)成本而獲得稅收優(yōu)惠的公司,對(duì)此更是怨聲載道。由此,美國(guó)分別于1988、1994、1998年三次對(duì)《反海外腐敗法》進(jìn)行修訂,以更適應(yīng)國(guó)際市場(chǎng)的現(xiàn)實(shí)情況,同時(shí)大力推進(jìn)《反海外腐敗法》的國(guó)際化。具體而言,修改后的《反海外腐敗法》主要有幾個(gè)變化。

          第一,對(duì)國(guó)際商業(yè)中的一些費(fèi)用,比如用以促進(jìn)外國(guó)政府機(jī)構(gòu)加快履行日常政府活動(dòng)的小額支出即“潤(rùn)滑費(fèi)”,進(jìn)行了合法化處理。

          第二,擴(kuò)大了該法的適用對(duì)象,從先前的美國(guó)公司和個(gè)人,擴(kuò)展到和美國(guó)有一定關(guān)系的外國(guó)企業(yè)、自然人或者母公司等。只要在美國(guó)上市、使用美元結(jié)算,或者僅僅通過(guò)設(shè)在美國(guó)的服務(wù)器(如谷歌郵箱或微軟郵箱)收發(fā)、存儲(chǔ)(甚至只是過(guò)境)電子郵件促成腐敗行為發(fā)生,這些都被視為利用了美國(guó)的國(guó)際貿(mào)易工具而被納入該法適用范圍。

          第三,要求美國(guó)總統(tǒng)采取行動(dòng),促成其他國(guó)家出臺(tái)與《反海外腐敗法》類似的法律。同時(shí),在美國(guó)霸權(quán)的極力推動(dòng)下,《反海外腐敗法》國(guó)際化取得了重要進(jìn)展。加拿大一些國(guó)家就出臺(tái)類似《反海外腐敗法》的國(guó)內(nèi)法。經(jīng)濟(jì)合作與發(fā)展組織(OECD)則也于1997年頒布《國(guó)際商業(yè)交易活動(dòng)反對(duì)行賄外國(guó)公職人員公約》。

          腐敗是阻礙人類社會(huì)發(fā)展的一大毒瘤。特別是在當(dāng)今全球深度一體化的背景下,沒(méi)有國(guó)家能夠獨(dú)善其身,必須團(tuán)結(jié)起來(lái)共同致力于反腐。《反海外腐敗法》本是美國(guó)單方面的國(guó)際反腐行動(dòng),但鑒于美國(guó)在世界體系中的重要地位,其影響逐漸擴(kuò)大,在一定程度上推動(dòng)全球反腐實(shí)現(xiàn)了從無(wú)到有,并逐漸演變成一個(gè)全球腐敗治理機(jī)制。

          當(dāng)然,我們也必須認(rèn)識(shí)到,美國(guó)制定該法律并在國(guó)際層面積極推廣之,并非全然出于反腐倡廉的道德境界,還有為與蘇聯(lián)爭(zhēng)霸謀求道德高地的戰(zhàn)略考量。換言之,美國(guó)“高尚”行為背后也摻雜著與蘇聯(lián)爭(zhēng)霸的私心雜念。而這也為蘇聯(lián)解體后,美國(guó)濫用《反海外腐敗法》為其私利服務(wù)留下了伏筆。

          美國(guó)《反海外腐敗法》被霸權(quán)濫用

          近年來(lái),美國(guó)《反海外腐敗法》越來(lái)越被霸權(quán)濫用。首先,雖然民粹主義可以利用反腐旗號(hào)上臺(tái),卻并非真心反腐,反而往往使腐敗形勢(shì)更加惡化。比如,印度的第一個(gè)反腐敗政黨“普通人黨”,在2015年新德里的地方選舉中異軍突起,一舉拿下70個(gè)立法會(huì)議席中的67個(gè)。但是好景不長(zhǎng),很快該黨就因?yàn)閮?nèi)斗、骯臟政治以及機(jī)制失調(diào),而導(dǎo)致公眾倍感失望。意大利的著名右翼民粹主義政黨也因卷入腐敗丑聞而遭受沉重打擊,導(dǎo)致該黨在2017年的中期選舉中丟掉主要大城市的執(zhí)政權(quán)。法國(guó)最大的民粹主義政黨——國(guó)民陣線的主席小勒龐,也因讓其保鏢及助理等非歐洲議會(huì)工作人員在歐洲議會(huì)領(lǐng)“空餉”,而被法國(guó)司法機(jī)關(guān)立案調(diào)查,并有10余名“國(guó)民陣線”議員涉入此案。

          其次,美國(guó)總統(tǒng)特朗普本身已成為廉政高風(fēng)險(xiǎn)的重點(diǎn)監(jiān)視對(duì)象,其反腐舉措更多的是一種“美國(guó)優(yōu)先”的手段。作為民粹主義興起的代表,特朗普雖然藉著反腐的緣由上臺(tái),在競(jìng)選期間也反復(fù)發(fā)出要抽干華盛頓腐敗沼澤的豪言壯語(yǔ),但是其許多舉措似乎正在開(kāi)反腐的倒車。而且,特朗普也因其巨大的商業(yè)帝國(guó)背景和聯(lián)系,成為廉政高風(fēng)險(xiǎn)的重點(diǎn)監(jiān)視對(duì)象。國(guó)外在這方面的討論很多,甚至有的民間組織還每月發(fā)布特朗普腐敗風(fēng)險(xiǎn)監(jiān)督報(bào)告,梳理分析所有可能指控特朗普涉嫌腐敗的法律條款等。

          不少人認(rèn)為,特朗普總統(tǒng)及其行政當(dāng)局某些做法不僅不合乎倫理,而且存在違法行為。特朗普就職不久,華盛頓的一家非盈利組織——“責(zé)任與倫理公民”,就正式向地方法院提起了針對(duì)特朗普的訴訟,控告特朗普違反了美國(guó)憲法中規(guī)定的“外國(guó)收益條款”。2017年6月中旬,華盛頓特區(qū)總檢察長(zhǎng)卡爾·拉辛及馬里蘭州總檢察長(zhǎng)布萊恩·弗洛西也對(duì)特朗普提起訴訟,指控他存在“史無(wú)前例的違憲行為”。該訴訟還宣稱,特朗普所繼續(xù)擁有的一個(gè)全球性的商業(yè)帝國(guó)已使總統(tǒng)“深深的陷入一個(gè)由國(guó)外及國(guó)內(nèi)政府行動(dòng)者組成的集團(tuán)中”,并且破壞了美國(guó)的政治體系的廉潔性。

          早在2012年,特朗普就公開(kāi)抨擊《反海外腐敗法》為“荒謬和糟糕的法律”。不少觀察家擔(dān)心特朗普會(huì)削弱《反海外腐敗法》。事實(shí)上,特朗普和共和黨領(lǐng)導(dǎo)的國(guó)會(huì)已經(jīng)放棄奧巴馬政府在打擊石油和天然氣行業(yè)反賄賂的努力,美國(guó)內(nèi)務(wù)部最近也采取行動(dòng)停止了對(duì)《采掘業(yè)透明倡議》的執(zhí)行。美國(guó)退出TPP也被不少人認(rèn)為是美國(guó)反腐的倒退和損失,因?yàn)槠渲杏袑iT的透明與反腐條款將反腐與貿(mào)易聯(lián)系起來(lái),而這耗掉了不少廉政工作者的努力和心血。而且,更令人擔(dān)憂的是,特朗普的腐敗表象以及抵制防止利益沖突舉措的態(tài)度極可能為國(guó)內(nèi)的其他腐敗官員所效仿。

          總之,不管是在美國(guó)國(guó)內(nèi)還是國(guó)外,美國(guó)政府過(guò)去幾十年苦心經(jīng)營(yíng)起來(lái)的廉潔領(lǐng)袖形象似乎在特朗普當(dāng)選后短暫的時(shí)間里出現(xiàn)了快速的崩塌。開(kāi)反腐倒車的特朗普政府,無(wú)疑已經(jīng)使以廉潔模范自居的美國(guó)開(kāi)始成為反腐的笑柄。當(dāng)然,這對(duì)全球反腐事業(yè)也構(gòu)成一定的沖擊。

          然而,就是這樣一位對(duì)反腐不屑一顧的總統(tǒng),卻在其任上開(kāi)始大肆啟動(dòng)對(duì)外國(guó)企業(yè)涉嫌賄賂的處罰,力度之大、金額之高令人訝然。這從下圖2016-2018年的黃色部分所代表的對(duì)外處罰金額就可見(jiàn)一斑。

          圖1:美國(guó)通過(guò)《反海外腐敗法》對(duì)企業(yè)實(shí)體的處罰一覽(圖表引自http://fcpa.stanford.edu/statistics-analytics.html?tab=2,2019年6月9日訪問(wèn))

          啟示

          第一,我們應(yīng)該客觀看待美國(guó)《反海外腐敗法》的歷史功績(jī)。不容否認(rèn),美國(guó)制定和推廣該法對(duì)于形成今天全球腐敗治理有著重要的推動(dòng)作用。打造全球廉潔的從商環(huán)境無(wú)疑仍然具有感召力,并應(yīng)成為世界各國(guó)共同努力的目標(biāo)。

          第二,對(duì)于美國(guó)利用其霸權(quán)優(yōu)勢(shì)及長(zhǎng)臂管轄手段打擊國(guó)外競(jìng)爭(zhēng)企業(yè)應(yīng)該引起世人的高度重視和清醒認(rèn)識(shí)。事實(shí)上,不僅是在利用《反海外腐敗法》方面,當(dāng)前特朗普政府的“美國(guó)優(yōu)先”戰(zhàn)略正在將其過(guò)去幾十年辛辛苦苦營(yíng)造的秩序和制度所葬送。

          第三,中國(guó)或可扛起促進(jìn)全球腐敗治理的大旗。一方面注重發(fā)揮《反海外腐敗法》對(duì)于國(guó)際治理的積極促進(jìn)作用,另一方面帶動(dòng)全球堅(jiān)決抵制其被某些霸權(quán)私用濫用。這對(duì)于進(jìn)一步提升我國(guó)在全球舞臺(tái)的形象,提高中國(guó)智慧和中國(guó)方案的感召力,并維護(hù)世界的公平與正義,都有重要的意義。

          、前面的話

          本文主要的內(nèi)容是幫助讀者朋友梳理chrome插件的tabs能力,如果您是第一次閱讀本文,也建議您在閱讀完本文后,嘗試看看我下面的這些系列文章,它們可以更好的幫您認(rèn)識(shí)和了解chrome插件:

          • chrome插件之從0到1
          • chrome插件之通信(V3版)
          • chrome插件之manifest配置
          • chrome插件之玩轉(zhuǎn)action

          1.能力

          一款瀏覽器插件具備非常強(qiáng)大的能力,它不僅可以向當(dāng)前所有的站點(diǎn)里注入腳本,對(duì)網(wǎng)站的功能進(jìn)行擴(kuò)展。更重要的是它還可以和瀏覽器的標(biāo)簽系統(tǒng)進(jìn)行交互,從而創(chuàng)建、修改、管理每一個(gè)tab,而這一切都基于插件系統(tǒng)為我們提供的tabs相關(guān)的API,chrome不僅提供了我們用于操作和管理tabs的API,而且還提供了和content腳本之間的通信方法。

          溫馨提示:

          Tabs API 只能在background腳本中以及option腳本、popup腳本、由chrome創(chuàng)建的tab中訪問(wèn)到,在content腳本中是無(wú)法訪使用的。

          換句話說(shuō),chrome有選擇性的給不同的腳本環(huán)境注入了不同的chrome對(duì)象,導(dǎo)致提供的API具備差異性。

          該圖是我們?cè)谔囟ōh(huán)境下可以通過(guò)chrome.tabs訪問(wèn)的所有的api,這些就是chrome為我們內(nèi)置的提供給開(kāi)發(fā)者的能力

          2.權(quán)限

          在之前的文章中我們提到過(guò),如果要使用某些特別的API,我們需要在插件配置文件manifest.json中配置相應(yīng)的權(quán)限聲明,但幸運(yùn)的是對(duì)于tabs相關(guān)的部分API不需要在manifest.json中顯式的配置“tabs”就可以直接使用。比如說(shuō): 創(chuàng)建一個(gè)新的tab,重新加載某個(gè)tab,或者導(dǎo)航到另外一個(gè)URL等等。

          但是下面的這些API在使用的時(shí)候,則需要加上相關(guān)的配置才可以使用,比如說(shuō):

          • permission
          • 如果你希望通過(guò)特定的條件找到某些tabs,你需要使用 chrome.tabs.query(queryInfo , callback) 這個(gè)API,這個(gè)時(shí)候就需要顯示的在manifest.json中permission中添加“tabs”聲明。
          • host permission 如果你希望能夠?qū)χ付ǖ膖ab動(dòng)態(tài)的在其中注入并執(zhí)行一段腳本,或者注入、移除某一段css樣式,那么你可能需要用到這些API:

          chrome.tabs.executeScript() // 注入一段腳本并執(zhí)行

          chrome.tabs.insertCss() // 注入一段css樣式

          chrome.tabs.removeCss() // 移除一段css樣式

          • 這個(gè)時(shí)候就需要在manifest.json中顯式的聲明需要命中的url。

          {

          // manifest.json "host_permissions":[ "<all_urls>" ] // 支持正則匹配正則

          }

          二、API

          接下來(lái)我們一一通過(guò)案例來(lái)認(rèn)識(shí)他們,從而感受每一個(gè)API的具體行為以及他們的使用條件、注意事項(xiàng)等等。

          1. 創(chuàng)建

          我們可以通過(guò)這個(gè)API來(lái)創(chuàng)建一個(gè)新的tab,這個(gè)tab和普通的站點(diǎn)不一樣,屬于插件所屬的頁(yè)面,因此支持跨域請(qǐng)求、獲取更多的chrome提供的方法。

          // background.js

          chrome.runtime.onInstalled.addListener(({reason})=> {

          if (reason==='install') {

          chrome.tabs.create({

          url: "newtab.html" // 相對(duì)于background腳本的路徑下需要有一個(gè)newtab.html文件

          });

          }

          });

          上面的腳本意味著在插件第一次安裝完成之后,就會(huì)立馬創(chuàng)建一個(gè)新的標(biāo)簽頁(yè),所以如果我們想要在任何時(shí)候創(chuàng)建一個(gè)新的tab,就可以使用這個(gè)API,行業(yè)內(nèi)很多插件的工作臺(tái)都是創(chuàng)建一個(gè)新的tab頁(yè)進(jìn)行工作的,比如著名的代理插件SwitchySharp

          該api默認(rèn)支持,不需要額外的manifest配置

          2. 查找

          我們可能有這樣的需要,獲取當(dāng)前瀏覽器窗口處于激活狀態(tài)的tab頁(yè)面,因?yàn)閷?duì)于同一個(gè)窗口,有且只有會(huì)一個(gè)tab是展示在用戶面前的,我們把這樣的tab稱為激活狀態(tài),這個(gè)時(shí)候我們就需要用到下面的api。

          async function getCurrentTab() { let queryOptions={ active: true }; let [tab]=await chrome.tabs.query(queryOptions); return tab; }

          調(diào)用上面的方法,你就可以獲得當(dāng)前窗口激活的那個(gè)tab的實(shí)例對(duì)象了,從這個(gè)對(duì)象中,你可以獲取到對(duì)應(yīng)的tab唯一的id、url、圖標(biāo)等信息。

          值得注意的是,如果chrome瀏覽器打開(kāi)了多個(gè)窗口,就意味著可能每一個(gè)窗口都會(huì)存在一個(gè)激活的tab,因此我們獲取的tab就會(huì)是多個(gè),這個(gè)時(shí)候如果只是解構(gòu)出第一個(gè)可能是不夠嚴(yán)謹(jǐn)?shù)摹?/span>

          因此我們可以通過(guò)添加搜索條件來(lái)精確的查找:

          async function getCurrentTab() {

          let queryOptions={

          active: true , currentWindow:true

          };

          let [tab]=await

          chrome.tabs.query(queryOptions);

          return tab;

          }

          通過(guò)添加一個(gè)參數(shù)currentWindow,意味著只搜索腳本運(yùn)行所在窗口的激活的tab,這個(gè)時(shí)候肯定只會(huì)查找出唯一的一個(gè)tab,解構(gòu)第一個(gè)就不會(huì)有問(wèn)題。

          搜索條件除了上述之外,還有下面可以選擇:

          參數(shù)

          類型

          作用

          active

          boolean

          是否處于激活狀態(tài)

          audible

          boolean

          是否處于播放音頻狀態(tài)

          currentWindow

          boolean

          是否處于腳本所在窗口內(nèi)

          groupId

          number

          是否處于某個(gè)分組內(nèi)

          highlighted

          boolean

          是否處于高亮狀態(tài)

          index

          number

          窗口從左往右第index個(gè)tab

          pinned

          boolean

          是否處于被固定的狀態(tài)

          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

          被固定是指那些通過(guò)右鍵點(diǎn)擊tab的時(shí)候,選擇固定在最左側(cè)的標(biāo)簽,并且可以固定多個(gè)。

          該api默認(rèn)支持,需要額外的manifest配置,需要顯式聲明“tabs”的permissions

          3.發(fā)送消息

          我們可以很方便的給指定的tab發(fā)送消息,一般來(lái)說(shuō)我們可以在content腳本中做消息的監(jiān)聽(tīng),接收到消息后使其執(zhí)行不同的業(yè)務(wù)邏輯。

          chrome.tabs.sendMessage(

          tabId: number, // 目標(biāo)tab的id

          message: any, // 發(fā)送信息

          options?: object, // 其他配置項(xiàng)

          callback?: function, // 回調(diào)函數(shù) )

          上面這個(gè)是V3版本的插件使用的,在V2版本中我們使用chrome.tabs.sendRquest()

          // 在v3版本中已廢棄

          chrome.tabs.sendRequest(

          tabId: number, // 目標(biāo)tab的id

          request: any, // 發(fā)送信息

          callback?: function, // 回調(diào)函數(shù)

          )

          4.修改

          如果我們希望修改一個(gè)tab的一些參數(shù)信息,我們可以選擇使用下面這個(gè)API:

          chrome.tabs.update( tabId?: number, updateProperties: object, callback?: function, )

          其中updateProperties的值就是上面提到的queryOptions的屬性保持一致,例如我們可以動(dòng)態(tài)的更改指定tab的title、url、pinned等狀態(tài)屬性!

          5.縮放比

          當(dāng)我們按住ctrl的同時(shí)再滑動(dòng)鼠標(biāo)滾輪的話就可以調(diào)整頁(yè)面的縮放比例,這個(gè)可能大家平時(shí)都深有體會(huì),但是實(shí)際上這個(gè)也可以通過(guò)插件給我們提供的API來(lái)動(dòng)態(tài)的進(jìn)行調(diào)整:

          chrome.tabs.setZoom( tabId?: number, zoomFactor: number, // 縮放比例 callback?: function, )

          6.移動(dòng)/移除/刷新

          我們介紹的第一個(gè)API就展示了如何創(chuàng)建一個(gè)新的tab,他會(huì)默認(rèn)創(chuàng)建在最末尾,也就是最右側(cè),如果這個(gè)放置位置我們不滿意,我們也可以將其放置在我們想要的位置。

          移動(dòng)

          chrome.tabs.move(

          tabIds: number | number[],

          moveProperties: object,

          callback?: function,

          )

          type moveProperties={ index?:number, // 想要移動(dòng)至的index索引位置. `-1` 移動(dòng)至窗口末尾.

          windowId?:number // 移動(dòng)至的窗口id

          }

          移除

          chrome.tabs.remove( tabIds: number | number[], callback?: function, )

          刷新

          chrome.tabs.reload( tabId?: number, reloadProperties?: object, callback?: function, ) type reloadProperties={ bypassCache?:boolean // 是否繞過(guò)本地緩存 默認(rèn)不繞過(guò),也就是使用本地緩存。 }

          7.導(dǎo)航

          我們可以通過(guò)插件來(lái)控制一個(gè)tab的前進(jìn)后退(如果他們都曾有過(guò)跳轉(zhuǎn)的記錄)

          chrome.tabs.goBack( // 回到最近的一次歷史記錄 tabId?: number, callback?: function, ) chrome.tabs.goForward( // 去到下一個(gè)歷史記錄,如果有的話 tabId?: number, callback?: function, )

          8.丟棄/復(fù)制

          當(dāng)我們的tab開(kāi)的特別多的時(shí)候,瀏覽器會(huì)有個(gè)小優(yōu)化,對(duì)于某些長(zhǎng)時(shí)間不用的tab,瀏覽器會(huì)清空內(nèi)存中對(duì)其的狀態(tài)存貯,因此當(dāng)我們?cè)俅螌⑵浼せ顣r(shí)會(huì)重新加載!這個(gè)過(guò)程插件也提供了API可以幫助我們做到:

          chrome.tabs.discard( tabId?: number, callback?: function, ) chrome.tabs.duplicate( // 這個(gè)API與discard相反,可以幫助我們復(fù)制一個(gè)一摸一樣的tab標(biāo)簽 tabId: number, callback?: function, )

          9.分組

          如果我們希望將某些具備相似特征的網(wǎng)站分成一個(gè)組,使其能夠在視圖上更好的被察覺(jué),那么我們就可以通過(guò)插件為我們提供的API來(lái)進(jìn)行實(shí)現(xiàn):

          第一步:篩選出希望分到同一組的tabs

          const tabs=await chrome.tabs.query({ url: [ "https://developer.chrome.com/*"], });

          根據(jù)前面的知識(shí),我們很容易就可以知道tabs就是域名為 "developer.chrome.com" 開(kāi)頭的所有站點(diǎn)的tab集合;

          第二步:將他們分為一組

          const tabIds=tabs.map(({ id })=> id); const group=await chrome.tabs.group({ tabIds });

          上圖中就可以看到所有符合條件的站點(diǎn)就被分為同一個(gè)組了,這個(gè)API的使用方式是:

          chrome.tabs.group( options: GroupOptions, callback?: function, ) type GroupOptions={ tabIds?:number[], // 希望被分組的tab的id的集合 groupId?:number, // 已有的分組 createProperties?:{ windowId?:number // 希望分組被創(chuàng)建在那個(gè)窗口, 默認(rèn)是腳本所在窗口 } }

          額外的話:

          如果我們希望在分組上再加上一個(gè)樣式或者字樣作為標(biāo)記的話,也可以這樣做:

          // 第一步: 在manifest.json中添加“tabGrpups”的權(quán)限 { ... "permissions":[ "tabGroups" ] } //第二步: chrome.tabGroups.update(group, { title: "這是分組1" , color:'red' });

          就可以修改這個(gè)分組的一些特征,上面是增加了一個(gè)標(biāo)題,效果如下:

          三、實(shí)戰(zhàn)

          以上我們介紹了基本的API,接下來(lái)我們通過(guò)一些案例來(lái)實(shí)際感受一下每個(gè)API的作用:

          準(zhǔn)備以下的項(xiàng)目:

          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>我是一個(gè)由chrome插件創(chuàng)建的頁(yè)面</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>創(chuàng)建新的頁(yè)面</h1> <button id="create-tab">創(chuàng)建</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>是否屬于當(dāng)前窗口:</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>查找結(jié)果:</div> <div id="search-result"></div> </div> </section> <section> <h1>發(fā)送消息</h1> <input type="color" id="send-value" /> <button id="send-btn">變色吧</button> </section> <section> <h1>刪/改/移/丟棄/復(fù)制</h1> <div> <input type="text" id="move-index" /> <button id="move">移動(dòng)當(dāng)前的tab</button> </div> <div> <button id="remove">移除當(dāng)前的tab</button> </div> <div> <button id="reload">刷新當(dāng)前的tab</button> </div> <div> <input type="text" id="discard-value" /> <button id="discard">丟棄</button> </div> <div> <button id="duplicate">復(fù)制</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">調(diào)整</button> </div> </section> <section> <h1>分組</h1> <div> <input type="text" id="group-title" /> <button id="group">使用查詢的結(jié)果進(jìn)行分組</button> </div> </section> <section> <h1>導(dǎo)航</h1> <div> <button id="goForward">前進(jìn)</button> <button id="goBack">前進(jìn)</button> </div> </section> <script src="./popup.js"></script> </body> </html>

          popup.js

          document.getElementById("create-tab").addEventListener("click", ()=> { chrome.tabs.create({ url: "newtab.html", // 相對(duì)于background腳本的路徑下需要有一個(gè)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); });

          以上的資源我會(huì)放到github上,大家可以download下來(lái)直接在自己的瀏覽器上運(yùn)行,查看效果,也希望有收獲后給不吝star哈!。

          下面是我本地的測(cè)試效果:

          創(chuàng)建頁(yè)面/發(fā)送消息

          查詢

          刪/改/更新

          分組

          有了以上的武器,就可以玩轉(zhuǎn)tabs啦!一起開(kāi)始開(kāi)發(fā)chrome插件吧!

          四、最后的話

          以下是我的其他文章,歡迎閱讀

          保姆級(jí)講解JS精度丟失問(wèn)題(圖文結(jié)合)

          shell、bash、zsh、powershell、gitbash、cmd這些到底都是啥?

          從0到1開(kāi)發(fā)一個(gè)瀏覽器插件(通俗易懂)

          用零碎時(shí)間個(gè)人建站(200+贊)

          另外我有一個(gè)自己的網(wǎng)站,歡迎來(lái)看看 new-story.cn

          創(chuàng)作不易,如果您覺(jué)得文章有任何幫助到您的地方,或者觸碰到了自己的知識(shí)盲區(qū),請(qǐng)幫我點(diǎn)贊收藏一下,或者關(guān)注我,我會(huì)產(chǎn)出更多高質(zhì)量文章,最后感謝您的閱讀,祝愿大家越來(lái)越好。


          主站蜘蛛池模板: 欧美激情一区二区三区成人| 午夜一区二区免费视频| 一本久久精品一区二区| 精品久久综合一区二区| 精品视频一区二区三区四区五区| 无码人妻精品一区二区蜜桃网站| 亚洲一区二区精品视频| 日本高清天码一区在线播放| 亚洲视频一区二区三区四区| 无码人妻精品一区二区在线视频| 国产成人精品一区在线| 精品乱码一区内射人妻无码| 无码日韩人妻av一区免费| 农村乱人伦一区二区| 日韩免费视频一区二区| 国产精品第一区第27页| AV怡红院一区二区三区| 一区视频在线播放| 精品中文字幕一区在线| 武侠古典一区二区三区中文| 天堂va视频一区二区| 日韩三级一区二区| 日韩美女视频一区| 波多野结衣一区二区三区88| 偷拍精品视频一区二区三区| 国产成人一区二区精品非洲| 无码日韩精品一区二区人妻 | 激情久久av一区av二区av三区| 久久精品一区二区三区AV| 精品国产一区二区三区色欲| 亚洲日韩中文字幕无码一区| 国产一区二区三区小说| 国产一区二区在线观看视频| 日本中文一区二区三区亚洲| 一区二区三区日本视频| 国产一区二区三区夜色| 无码人妻精品一区二区| 一区二区传媒有限公司| 视频一区二区中文字幕| 亚洲熟女少妇一区二区| 亚洲视频一区在线播放|