【Chrome插件】零基础学习Chrome

1.“重新加载”插件问题

在“重新加载”插件时,错误的插件将不会加载进去,且不会不错,只会保留上一次的可用插件,并把启用去除

2.上下文环境问题

在extension的编写过程中,会发现:比如我在background.js里面定义了一个函数,然后在popup页面中不能调用!进一步研究,你会发现后台和popup两者之间,并不能共享变量。事实上,这里有三个环境(上下文),为了描述方便,我喜欢称之为background、popup、content。算上浏览页面自身的脚本,一共有四个环境。他们相互独立,拥有不同的上下文,不能共享任何js变量

3.js代码出错

在html中直接嵌入的js代码,错误语句之前的代码都能执行

4.content_script调用页面js函数

两种方法可间接执行目标函数
创建一按钮节点,使其点击事件自动执行,执行方法为登陆按钮执行的方法(起到模拟执行作用)

var body = document.body; 
var input = document.createElement("input"); 
input.type = "button";
body.appendChild(input);
input.setAttribute("onClick","DoSubmit()");//input.onclick=DoSubmit;此种写法,无法生效
input.click();
同理。给boay增加点击事件,然后执行
var tmp=document.body.onclick; //保存原来的事件句柄
document.body.setAttribute("onclick","DoSubmit()");
document.body.click();
if(tmp) document.body.onclick=tmp; //恢复原来的事件句柄

5.跨域异步请求案例(如访问获得ip接口)

manifest.json
"permissions": [ "http://sneezryworks.sinaapp.com/ip.php" ]
... .js
function httpRequest(url, callback){ 
var xhr = new XMLHttpRequest(); 
xhr.open("GET", url, true); 
xhr.onreadystatechange = function() { 
if (xhr.readyState == 4) { 
callback(xhr.responseText); 
} 
} 
xhr.send(); 
} 
httpRequest('http://sneezryworks.sinaapp.com/ip.php', 		function(ip){ document.getElementById('ip_div').innerText = ip; });

6.background常驻后台

在Manifest中指定background域可以使扩展常驻后台。background可以包含三种属性,分别是scripts、page和persistent
persistent属性定义了常驻后台的方式——当其值为true时,表示扩展将一直在后台运行,无论其是否正在工作;当其值为false时,表示扩展在后台按需运行,这就是Chrome后来提出的Event
Page。Event
Page可以有效减小扩展对内存的消耗,如非必要,请将persistent设置为false。persistent的默认值为true。

7.数据存储

(http://www.ituring.com.cn/book/miniarticle/60274)

  1. 第一种是使用HTML5的localStorage;
  2. 第二种是使用Chrome提供的存储API;
  3. 第三种是使用Web SQL Database。

(1.)localStorage是HTML5新增的方法
它允许JavaScript在用户计算机硬盘上永久储存数据(除非用户主动删除)。
localStorage只能储存字符串型的数据,无法保存数组和对象,但可以通过join、toString和JSON.stringify等方法先转换成字符串再储存
通过声明unlimitedStorage权限,Chrome扩展和应用可以突破这一限制
ex:
var city = localStorage.city || ‘beijing’;//读取city值,没有则默认为’beijing’
localStorage.city = document.getElementById(‘city’).value;
localStorage除了使用localStorage.namespace的方法引用和写入数据外,还可以使用localStorage[‘namespace’]的形式。请注意第二种方法namespace要用引号包围,单引号和双引号都可以。如果想彻底删除一个数据,可以使用localStorage.removeItem(‘namespace’)方法。

首先localStorage是基于域名的,这在前面的小节中已经提到过了。而content_scripts是注入到用户当前浏览页面中的,如果content_scripts直接读取localStorage,所读取到的数据是用户当前浏览页面所在域中的。所以通常的解决办法是content_scripts通过runtime.sendMessage和background通信,由background读写扩展所在域(通常是chrome-extension://extension-id/)的localStorage,然后再传递给content_scripts。
(2.)chromeAPI
对于每种储存区域,Chrome又提供了5个方法,分别是get、getBytesInUse、set、remove和clear。

8.扩展页面间的通信

(http://www.ituring.com.cn/book/miniarticle/60272)
Chrome提供了4个有关扩展页面间相互通信的接口,分别是runtime.sendMessage、runtime.onMessage、runtime.connect和runtime.onConnect
runtime.sendMessage完整的方法为:
chrome.runtime.sendMessage(extensionId, message, options, callback)
runtime.onMessage完整的方法为:
chrome.runtime.onMessage.addListener(callback)

为了进一步说明,下面举一个例子。
在popup.html中执行如下代码:
chrome.runtime.sendMessage(‘Hello’, function(response){ document.write(response); });
在background中执行如下代码:
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){ if(message == ‘Hello’){ sendResponse(‘Hello from background.’); } });

9.不要在popup页面的js空间变量中保存数据。

由于popup页面只在用户点击图标时才会开启,当用户关闭这个页面时就会停止,并没有一个从始至终的实例分配给popup页面。所以每当用户打开popup页面时,它都是崭新的,之前保存在变量中的数据都会消失。如果需要通过popup页面保存用户的数据,可以通过通信将数据交给后台页面处理,或者通过localStorage和chrome.storage将数据保存在用户的硬盘上。

10.右键菜单

Chrome提供了三种方法操作右键菜单,分别是create、update和remove,对应于创建、更新和移除操作。

chrome.contextMenus.create({ type: 'normal', title: 'Menu A', id: 'a' });
chrome.contextMenus.create({ type: 'radio', title: 'Menu B', id: 'b', checked: true }); 
chrome.contextMenus.create({ type: 'checkbox', title: 'Menu D', id: 'd', checked: true });

11.地址栏Omnibox有四种事件:

onInputStarted、onInputChanged、onInputEntered和onInputCancelled,分别用于监听用户开始输入、输入变化、执行指令和取消输入行为。其中执行指令是指用户敲击回车键或用鼠标点击建议结果。

12.content_script 匹配规则:

http://open.chrome.360.cn/extension_dev/match_patterns.html)
另外, 这两个属性与matches属性的语法是不同的, 它们更灵活一些。 在这两个属性中可以包含号和?号作为通配符。 其中可以匹配任意长度的字符串,而?匹配任意的单个字符。
例如,语句"http://???.example.com/foo/"" 可以匹配下面的所有情况:
"http://www.example.com/foo/bar"
"http://the.example.com/foo/"
但是它不能匹配下面的这些情况:
"http://my.example.com/foo/bar"
"http://example.com/foo/"
"http://www.example.com/foo
这里展示一些不合法的模式匹配的例子:
错误的模式匹配 错误原因
http://www.google.com 没有说明路径
http://foo/bar 在域名部分使用’‘时,’
‘后边只能是’.’ 或者 ‘/’
http://foo..bar/baz 如果’'出现在host部分时, ''只能出现在开头
http:/bar 少写了协议分隔符("/" 应该是"//")
foo://
无效的协议

13.Manifest的content_scripts属性值为数组类型

数组的每个元素可以包含matches、exclude_matches、css、js、run_at、all_frames、include_globs和exclude_globs等属性。其中
matches属性定义了哪些页面会被注入脚本,
exclude_matches则定义了哪些页面不会被注入脚本,
css和js对应要注入的样式表和JavaScript,
run_at定义了何时进行注入,
all_frames定义脚本是否会注入到嵌入式框架中,
include_globs和exclude_globs则是全局URL匹配,最终脚本是否会被注入由matches、exclude_matches、include_globs和exclude_globs的值共同决定。简单的说,如果URL匹配mathces值的同时也匹配include_globs的值,会被注入;如果URL匹配exclude_matches的值或者匹配exclude_globs的值,则不会被注入

ps:run_at:
控制JS文件注入的时机,如"document_start", “document_end”, “document_idle”。默认"document_idle"
"document_start"表示在CSS文件之后,DOM构建或其他脚本运行之前,注入JS文件。
“document_end”,表示在DOM构建结束之后,图片或框架加载之前,注入JS文件。
"document_idle"表示在"document_end"与触发window.onload事件之间的某个时间,注入JS文件,具体时间可以根据页面的内容和加载的进度优化。

14.网络通信

Chrome应用通过sockets接口支持TCP和UDP协议,使网络通信成为可能。使用sockets接口时,声明权限比较特殊,并不在permissions中声明,而是直接在Manifest的sockets中声明

"sockets": { 
"udp": {
		 "send": ["192.168.1.106:8000", ":8001"], "bind": ":8000" 
	}, "tcp" : { 
		"listen": ["host-pattern1", ...], ...
	 }
 }

如果想连接任意主机的任意端口可以声明为"send": “*”。主机和端口可以是一个特定的字符串,也可以是一个数组表示多个规则,如"bind": [":8000", “:8001”]。如果想连接192.168.1.106的任意端口可以声明为"send": “192.168.1.106”
a. UDP(http://www.ituring.com.cn/book/miniarticle/74723)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章