最近有点闲,手痒,就嘴贱提出帮运营,编辑们做点小工具。主要就是对页面做一些批量化的操作,以减少他们的手工劳动时间,同时也避免一些人工操作出错的风险。
从前做这些事情,都是用vc或者delphi,放个WebBrowser控件,或者做个BHO。不过这种方式需要编译生成exe或者dll,调试起来有点麻烦,而且这种做法是基于微软的COM技术,代码写起来很繁琐,很容易出错。由于IE内核只能在windows下运行,有一定的局限性。而且我的同事们现在都在使用mac,为了使用个小工具,还得装个虚拟机划不来,那就只好用chrome扩展来实现了。
chrome扩展有很多优点,它一般由js、html组成,无需编译,能操作DOM,能控制浏览器行为,能本地存储(localStorage),不过好像不能进行文件操作。
清单文件是chrome扩展必须的文件,它描述了扩展的信息以及组成部分。一个清单文件的大概内容如下:
{
"name": "chrome扩展测试",
"version": "1.0",
"manifest_version": 2,
"description": "chrome扩展测试。",
"browser_action": {
"default_icon": "logo.png",
"default_popup": "popup.html"
},
"background" : {
"persistent": true,
"scripts": ["bg.js"]
},
"content_scripts":[{
"matches":["*://*/*"],
"js":["content_scripts.js"]
}],
"permissions": [
"tabs","webNavigation"
]
}
browser_action字段定义了扩展的交互部分,它在浏览器的工具栏添加一个按钮,按钮图标在default_icon字段定义,当点击按钮时,会弹出字段default_popup指定的页面,通过弹出页面可以与用户交互。该页面生命周期为在弹出时创建,隐藏时释放,当有数据需要保存时,需要把数据传递到后台页面(background page),或者存储到本地,不然当弹出页关闭后,数据会丢失。
background字段定义了扩展的后台页面,后台页面是一个常驻后台的不可见页面,主要用来保存扩展状态,任务管理等,他在同一扩展中仅存在一个实例。
content_scripts字段定义了上下文脚本,用来和dom页面交互。它与加载它的页面生命周期相同。
browser action和background页面同在扩展进程的同一个线程中,可以通过chrome提供的api直接进行互相调用:
chrome.extension.getViews //获取交互页面
chrome.extension.getBackgroundPage //获取后台页面
content_scripts定义的脚本执行在浏览器加载的页面上下文,可以认为是被页面加载。由于不与后台页面在同一个进程,它们之间需要通过消息机制来传递信息:
chrome.runtime.sendMessage //发送消息
同时chrome为扩展提供了很多api供开发者使用,具体请参见 Chrome Platform APIs (需要)
定义好manifest.json文件,就可以开始编码了,以下示例演示一个时间扩展,点击工具栏按钮会弹出一个页面显示当前时间,浏览器每打开一个页面,也会在当前页的最上端显示时间(显示效果与具体页面有关。)。
首先在同目录下创建logo.png(工具栏按钮图标),popup.html(点击工具栏按钮弹出的页面),popup.js,content_scripts.js,bg.js文件,为了方便,我再放入一个jquery-2.1.3.min.js文件。
各文件内容如下:
popup.html
popup.js
setInterval(function(){
var now = chrome.extension.getBackgroundPage().getTime();
$("#currentTime").text("现在时间:" + now);
},500);
bg.js
function getTime(){
var now = new Date();
var nowString = now.getFullYear() + "-" +
(now.getMonth() + 1) + "-" + now.getDate() +
" " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
return nowString;
}
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if(request.cmd == "get-time"){
sendResponse(getTime());
}
});
content_scripts.js
setInterval(function () {
chrome.runtime.sendMessage(
{cmd: 'get-time'},
function (response) {
var timeNode = document.getElementById("testCurrentTime");
if (timeNode) {
timeNode.innerText = "现在时间:" + response;
}
else {
timeNode = document.createElement("p");
timeNode.id = "testCurrentTime";
timeNode.innerText = '现在时间:' + response;
document.body.insertBefore(timeNode,document.body.firstChild);
}
}
);
}, 500);
打包过程如下: