在这纷繁复杂的数字江湖之中,有一本神秘的秘籍悄然现世,名为《万字速通Chrome扩展开发》功法。此秘籍威力巨大,修炼者若能参透其中奥秘,便可在网络世界中纵横驰骋,操控网页如同掌控江湖风云。
每个功能均可单独修炼,开发完整Chrome扩展时又可融会贯通,发挥强大威力。
接下来,本文将逐一拆解各技能,从入门到精通,助大侠们掌握精髓,纵横Chrome扩展江湖。
话说武林之中,高手过招讲究见招拆招,而在这网络江湖里,用户浏览网页时也会遇到各种状况,此时便需要我们运用Chrome扩展的功力来化解。
比如uBlockOriginLite插件
所以知道操作用户正在浏览的页面的厉害了吧!
现在来做一个小Demo,简单体验一下操作用户正在浏览的页面的Dom这个能力。
Demo源码:
首先,创建以下文件和目录结构:
解释:
//初始化按钮移动功能的主函数functioninitializeButton(){//获取百度搜索按钮的包装元素constsearchButtonWrapper=document.getElementById('s_btn_wr');if(searchButtonWrapper){//定义按钮随机移动的函数functionrandomizeButtonPosition(){//生成200-500px范围内的随机位置constrandomTop=Math.floor(Math.random()*301+200);//301=(500-200+1)constrandomLeft=Math.floor(Math.random()*301+200);//设置按钮的定位和位置searchButtonWrapper.style.position='fixed';searchButtonWrapper.style.top=randomTop+'px';searchButtonWrapper.style.left=randomLeft+'px';}//当鼠标悬停在按钮上时触发随机移动searchButtonWrapper.addEventListener('mouseenter',randomizeButtonPosition);}}//首次执行初始化initializeButton();4.加载扩展完成以上步骤后,当你访问百度搜索网页时,将会永远点不到搜索按钮
试试看吧!
通过这个小Demo,大家已经知道了:
1.什么是操作用户正在浏览的页面Dom
2.如何操作用户正在浏览的页面Dom
这个技能很重要,但是单独使用这个技能并不能发挥它的厉害之处,只有与其他的技能结合才能形成必杀技。
请学习第二招
各位江湖豪杰,方才我们已见识了Chrome扩展操作用户正在浏览的页面的奇妙本领,可谓是在这数字江湖中渐入佳境。然而,江湖之路,总是充满了各种挑战与险阻,接下来我们便要踏入一个稍显棘手的领域——跨域请求。
跨域指的是JavaScript通过XMLHttpRequest请求数据时,调用JavaScript的页面所在的域和被请求页面的域不一致。对于网站来说,浏览器出于安全考虑是不允许跨域。另外,对于域相同,但端口或协议不同时,浏览器也是禁止的。下表给出了进一步的说明:
{..."permissions":["*://*.wikipedia.org/*"]}这样Chrome就会允许你的扩展在任意页面请求维基百科上的内容了。
接下来,我们将通过一个生动有趣的Demo,来详细阐述如何发送跨域请求。
Demo描述:演示如何在Chrome插件中实现跨域请求。点击【获取跨域图片】按钮,在popup页面展示跨域接口返回的图片。
Demo效果:
如何确定一个请求属于跨域请求,且该请求的接口未将关键响应头Access-Control-Allow-Origin配置为*
一、判断是否跨域首先,我们需要判断一个请求是否属于跨域请求。当以下情况发生时,可判定为跨域请求:
二、判断接口的关键响应头Access-Control-Allow-Origin配置在确认请求为跨域的基础上,我们进一步判断接口是否将关键响应头Access-Control-Allow-Origin配置为*。具体操作如下:
下面我们来探究一下,如果不配置host_permissions会引发何种情况呢?
1.删掉host_permissions配置文件内容
我们这样,把manifest.json文件中的host_permissions配置文件删掉:删掉之前:
"host_permissions":[//这里删掉],2.刷新插件
3.打开调试信息
4.查看错误删掉host_permissions配置文件内容之后,再去请求发现,确实是报错跨域问题了。
这样,你就学会了使用chrome扩展成功获取跨域请求内容的技能!此乃初入江湖的一大进步也!
各位江湖豪杰!在这Chrome扩展的奇妙江湖里,我们已然在诸多技能上有所建树,似那掌握了“跨域请求”的天涯咫尺步,可跨越疆界;又似精通“操作用户页面”的幻影迷踪手,能在页面DOM元素间穿梭自如。但江湖险恶,变幻莫测,仅靠这些恐怕还不足以立足。
今番要研习的是一门神秘莫测的奇功——常驻后台,此乃“隐世守护诀”。在这风云涌动的数字江湖中,此诀犹如一位隐世高手,悄然藏身于幕后,时刻守护着我们的网页江湖。
有时我们希望扩展不仅在用户主动发起时(如开启特定页面或点击扩展图标等)才运行,而是希望扩展自动运行并常驻后台来实现一些特定的功能,比如:
Chrome允许扩展应用在后台常驻一个页面以实现这样的功能。在一些典型的扩展中,UI页面,如popup页面或者options页面,在需要更新一些状态时,会向后台页面请求数据,而当后台页面检测到状态发生改变时,也会通知UI界面刷新。
后台页面与UI页面可以相互通信,这将在后续的章节中做进一步的说明,这里将主要说说后台页面是如何工作的。
在Manifest中指定background域可以使扩展常驻后台。background可以包含三种属性,分别是scripts、page和persistent。如果指定了scripts属性,则Chrome会在扩展启动时自动创建一个包含所有指定脚本的页面;如果指定了page属性,则Chrome会将指定的HTML文件作为后台页面运行。通常我们只需要使用scripts属性即可,除非在后台页面中需要构建特殊的HTML——但一般情况下后台页面的HTML我们是看不到的。persistent属性定义了常驻后台的方式——当其值为true时,表示扩展将一直在后台运行,无论其是否正在工作;当其值为false时,表示扩展在后台按需运行,这就是Chrome后来提出的EventPage。EventPage可以有效减小扩展对内存的消耗,如非必要,请将persistent设置为false。persistent的默认值为true。
接下来写个Demo体验一下。
Demo描述:用户可在选项页面添加关键词,后台脚本会自动运行,监测用户浏览的所有网页。当页面加载完成时,它会向网页注入一个脚本,遍历页面文本内容,使用高级的DOM操作技巧,精确查找用户设置的关键词。一旦找到,会使用Range对象将关键词用黄色高亮显示,同时不破坏原文档结构。
好了,可以看看效果了。只要设置好了关键词,随便进入哪个页面,都会把关键词标记为高亮黄色,并且还是静默运行,用户感知很低。
有个小问题:chrome.tabs.onHighlighted事件就是chrome.tabs.onActivated。这俩功能是一样的?为什么还要写两个,他们的不同是什么?
chrome.tabs.onHighlighted和chrome.tabs.onActivated这两个事件虽然在某些情况下可以实现类似的功能,但它们的触发条件和使用场景是不同的。
1.触发条件:
想象一下,在江湖中,大侠们拥有一个神奇的“百变如意囊”,可以根据不同的情况变幻出各种所需之物,满足各种需求。在Chrome扩展的世界里,这一技能也有着异曲同工之妙,带选项页面的扩展就如同这个神奇的“百变如意囊”,它能为我们的扩展增添更多的灵活性和个性化。
既然扩展允许用户进行个性化设置,就需要向用户提供一个选项页面。Chrome通过Manifest文件的options_page属性为开发者提供了这样的接口,可以为扩展指定一个选项页面。当用户在扩展图标上点击右键,选择菜单中的“选项”后,就会打开这个页面。
对于网站来说,用户的设置通常保存在Cookies中,或者保存在网站服务器的数据库中。对于JavaScript来说,一些数据可以保存在变量中,但如果用户重新启动浏览器,这些数据就会消失。那么如何在扩展中保存用户的设置呢?我们可以使用HTML5新增的localStorage接口。除了localStorage接口以外,还可以使用其他的储存方法。后面将专门拿出一节来说数据存储,这里我们先使用最简单的localStorage方法储存数据。
localStorage是HTML5新增的方法,它允许JavaScript在用户计算机硬盘上永久储存数据(除非用户主动删除)。但localStorage也有一些限制,首先是localStorage和Cookies类似,都有域的限制,运行在不同域的JavaScript无法调用其他域localStorage的数据;其次是单个域在localStorage中存储数据的大小通常有限制(虽然W3C没有给出限制),对于Chrome这个限制是5MB2;最后localStorage只能储存字符串型的数据,无法保存数组和对象,但可以通过join、toString和JSON.stringify等方法先转换成字符串再储存。
好了,可以看看效果了。
可以看到,点击【打开选项页面】
这里就是【选项页面】:
在这纷繁复杂的江湖之中,信息的传递至关重要。就如同武林高手们需要互通消息,协同作战一样,Chrome扩展中的不同页面之间也需要密切配合,这时候“传音入密术”便发挥了巨大的作用,此术可以让我们的扩展页面之间悄无声息地传递信息,就像高手们使用传音入密的功夫,将重要的消息准确无误地传达给对方,而旁人却无法察觉。
在Chrome扩展开发领域。,论是扩展内部多个页面,还是不同扩展的页面,数据传输能让它们及时获取彼此状态。
以音乐播放器扩展为例,当用户在popup页面点击音乐列表,就触发了一系列通信需求。此时,popup页面需将用户指令精准传达给后台页面,后台页面接收到指令后,随即启动相应音乐的播放流程。
Chrome为满足此类通信需求,提供了4个关键接口:runtime.sendMessage、runtime.onMessage、runtime.connect与runtime.onConnect。
值得特别指出的是,Chrome众多API中,多数无法在content_scripts中运行,但runtime.sendMessage和runtime.onMessage是难得的例外。这一特性,让扩展的其他页面与content_scripts之间实现了顺畅通信。
下面,我们深入剖析这两个接口的具体使用方法:
该方法的完整形式为:
chrome.runtime.sendMessage(extensionId,message,options,callback)2.runtime.onMessage此方法的完整形式为:
chrome.runtime.onMessage.addListener(callback)这里的callback是必填项,作为回调函数,它会接收三个参数:
随我做一个小Demo体验一下:
Demo描述:
此Demo展示了Chrome扩展中的简单消息传递机制。包含popup.html和background.js两部分。在popup.html的脚本popup.js中,当页面加载完成,会向后台发送'Hello'消息。而background.js中使用chrome.runtime.onMessage.addListener监听消息,若收到'Hello',将回复'Hellofrombackground.'。通过chrome.runtime.sendMessage和chrome.runtime.onMessage.addListener接口,实现了popup页面和后台页面之间的消息交互,让用户体验Chrome扩展页面间的通信功能。
在江湖中,大侠们常常需要一个能收纳各种宝贝和秘籍的神奇法宝,而“乾坤储物戒”就是这样的存在。它拥有着广阔的空间,可将各种物品收纳其中,方便我们随时取用。在Chrome扩展的世界里,“乾坤储物戒”也就是存储数据的技能,同样至关重要,我们可以使用它来存储各种信息,无论是用户的偏好设置、重要的数据,还是在江湖闯荡时收集的各种资料,都可以被安全地保存在这神奇的“储物戒”中。
通常来说,Chrome扩展可以采用以下三种方法中的一种来储存数据:
开发者应根据实际的情况选择上述三种方法中的一种或几种来存储扩展中的数据。由于我在上面小节中已经详细说了localStorage的使用方法,所以下面我将重点介绍后两种储存数据的方法。
Chrome为扩展应用提供了存储API,以便将扩展中需要保存的数据写入本地磁盘。Chrome提供的存储API可以说是对localStorage的改进,它与localStorage相比有以下区别:
Chrome同时还为存储API提供了一个onChanged事件,当存储区的数据发生改变时,这个事件会被激发。
WebSQLDatabase的三个核心方法为openDatabase、transaction和executeSql。openDatabase方法的作用是与数据库建立连接,transaction方法的作用是执行查询,executeSql方法的作用是执行SQL语句。
需要注意的是,以上几种数据的存储方式都不会对数据加密,如果储存的是敏感的数据,应该先进行加密处理。比如不要将用户密码的明码直接储存,而应先进行MD5加密。
从“操作用户正在浏览的页面”的“幻影迷踪手”,到“跨域请求”的“天涯咫尺步”,再到“常驻后台”的“隐世守护诀”,“带选项页面的扩展”的“百变如意囊”,“扩展页面间的通信”的“传音入密术”,以及“存储数据”的“乾坤储物戒”,我们逐步掌握了一系列实用而强大的技能。这些技能如同武林秘籍中的各种绝学,既可以单独施展,展现独特威力,又能相互配合,形成一套完整的武功体系,助你在Chrome扩展的开发江湖中纵横驰骋。
愿各位大侠在今后的开发之路上,灵活运用这些技能,不断创新,打造出更加出色的Chrome扩展,在数字江湖中留下属于自己的传奇故事。