手把手教你开发Chrome扩展

手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单

  1. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单
  2. 手把手教你开发Chrome扩展二:为html添加行为
  3. 手把手教你开发Chrome扩展三:关于本地存储数据

Chrome的更新速度可以说前无古人,现在我每天开机的第一件事就是打开Chrome检查是不是有了新版本。界面清爽、操作人性化、网络备份资料和快速的启动速度令我爱不释手,还有它拥有众多的扩展程序,相对于firefox的插件来说,数量上和质量上稍显不足,但相信chrome将会很快在扩展上超越firefox,firefox上内存占用上实在不令人满意,也许我使用firefox的一个原因就是因为firebug,不过相信chrome平台的类firebug插件也会很快出现。

Chrome的扩展开发十分简单,我们只需要掌握web开发的htm+CSS+Javascript,就能很快开发出自己的扩展。

你需要了解的内容

在开发前首先要掌握一些基础知识。

1、Chrome扩展文件

Chrome扩展文件以.crx为后缀名,在Google Chrome扩展官方网站下载扩展时,Chrome会将.crx文件下载到Chrome的Application Data文件夹的User Data\Temp下,一般是C:\Documents and Settings\User\Local Settings\Application Data\Google\Chrome\User Data\Temp,安装完成或者取消安装,该文件就会被删除。.crx实际上是一个压缩文件,使用解压文件打开这个文件就可以看到其中的文件目录,下图中是“关灯看视频”扩展的截图:

因此可以认为,我们实际上就是写一个Web应用,然后将按照Chrome的规定将一个快捷方式放在Chrome工具栏上。

2、Browser Actions(扩展图标)

把Browser Actions翻译成扩展图标不是很准确,但它的功能就是把你的应用显示在Chrome工具栏上。我们在上面看到一个文件manifest.json,就是使用这个文件来把相应的图标和其他参数注册到Browser Actions。比如下图中就是EverNote的扩展图标。

3、Page Actions(地址栏图标)

如果你熟悉一些Chrome插件的话,你一定会发现有些扩展的图标不是显示在地址栏的右边,而是显示在地址内部右方,这就是Page Actions地址栏图标。

可以看出上面中有三个Page Actions,图中我标出的是Chrome添加书签,现在你就会发现其实这个也是Chrome的扩展,只不是它是直接内置在Chrome的。

Page Actions与Browser Actions的区别就是Page Actions不是随时都是显示的,必须在特定的页面中这个功能才能使用。因此在开发中注意:如果不是全部页面中都能使用的功能请使用Page Actions方式。

4、popup弹出窗口

popup属于Browser Actions,当点击图标时出现这个窗口,可以在里面放置任何html元素,它的宽度是自适应的。当然,这个弹出窗口不会被Chrome拦截的:)

如下图中是evernote的popup窗口:

5、Background Pages后台页面

这个窗口不会显示,它是扩展程序的后台服务,它会一直保持运行。比如在一些需要数据保存程序中,如果当前用户关闭popup,就需要Background Pages来进行相应的操作。

自己动手做一个

我们以一个简单的任务管理程序来一步步讲解。

上图是界面实现,我们首先完成界面的显示部分,首先建立一个新文件夹,以扩展应用的名称为标题,我们这里的应用叫做MyTaskList。然后把找一个图标文件,放到文件夹中,也可直接右键下载我的这个图标:

图标文件不要小于19px*19px,但最好也不要超过这个尺寸,虽然大图它会自适应,但会使得应用文件变大。然后完成和未完成状态的两个图标放到资源文件中,可以建立任意文件夹放进去,因为CSS文件把定义它们的路径。

建立manifest.json来定义我们程序配置:

   "name" : "MyTaskList"
   "version" : "0.9.0"
   "description" : "Management my everyday's task lists."
   "browser_action" : { 
     "default_icon" : "icon.png"  ,
     "default_title" : "My Task List" ,
     "default_popup" : "popup.html"
  
}

其中name代表应用程序名,version代表版本号,description代表功能描述。这些在安装扩展后就能看到,见下图:

browser_action代表扩展图标段显示,它会定义图标地址、标题(也就是鼠标悬停提示)和默认的popup页面。我们这里定义的popup页面为popup.html。

接下来开始定义popup.html显示,它不需要使用<html>、<head>和<body>标签,可以直接写上样式、脚本和html。我们的popup.html源码为:

< style  type="text/css">
*{margin:0;padding:0;}
body{color:#333;overflow: hidden;margin: 0px;padding:5px;background: white;font-size:12px;}
img{margin:0 4px;}
#addItemDiv{color:#ccc;}
.hide{display:none;}
.show{display:block;}
.taskItem{cursor:pointer;}
input{width:100%;}
label.on{width:12px; display:inline-block; height:12px; background:url(images/bg_task_on.gif) no-repeat 0px 2px;}
label.off{width:12px; display:inline-block; height:12px; background:url(images/bg_task_off.gif) no-repeat 0px 2px;}
</ style >
< div  id="newItem" class="gray">添加新项</ div >
< div  id="addDiv" class="hide">< input  type="text" id="txtTitle" /></ div >
< div  id="taskItemList">
     < div  class="taskItem">
         < label  class="on"></ label >< span  class="taskTitle">新任务</ span >
     </ div >
     < div  class="taskItem">
         < label  class="off"></ label >< span  class="taskTitle">已完成任务</ span >
     </ div >
</ div >

打开预览,样子就已经出来了:

这样我们文件就已经建立完成,文件列表如下:

现在就可以先尝试把它打包装到自己的Chrome里。

首先打开Chrome-工具-扩展程序,展开开发人员模式,打到“打包扩展程序”按钮:

点击“打包扩展程序…”,弹出打包选择文件窗口,在扩展程序根目标中找到我们建立的文件夹,私有密码文件第一次不用选择:

点击确定,它会在根文件夹同一级生成MyTaskList.crx和MyTaskList.pem,MyTaskList.pem是程序签名文件,以新版本的开发中还需要这个文件,不要删除它。把MyTaskList.crx拖进Chrome窗体内,就会把这个应用MyTaskList安装在Chrome里。

我们的这个简单的模型就能看到效果了,下一节我们就会完善其中的代码。


手把手教你开发Chrome扩展二:为html添加行为

  1. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单
  2. 手把手教你开发Chrome扩展二:为html添加行为
  3. 手把手教你开发Chrome扩展三:关于本地存储数据

上一节我们已经讲了Chrome扩展的基础知识,并构建了基础的html,这一节我们将就html DOM添加部分添加脚本,即脚本在我们的popup页面中进行的操作,页面所产生的变化。

正常情况下数据处理加载完成状态,这些数据是从本地数据读取的。

点击“添加新项”,出现输入框,输入文字后回车提交数据:

添加完成后将数据存储,同时添加DOM元素:

考虑到功能最简化处理,点击已标为完成的任务,将提示“删除或重置为未完成”:

以上功能为最核心功能,可以在此基础上进行扩展,比如任务分组,修改任务,任务提醒,网络同步数据等等。

下面开始相应的脚本内容。

为了避免全局变量,使用匿名函数方式,所有事件处理及数据绑定均在此函数中进行,同时定义与jQuery中的$()类似的函数:

( function (){
     var  $= function (id){ return  document.getElementById(id);}
})();

建立Tasks对象,定义show()函数和hide()函数,同时存储几个常用的DOM对象。

var  Tasks = {
   show: function (obj){
     obj.className= '' ;
     return  this ;
   },
   hide: function (obj){
     obj.className= 'hide' ;
     return  this ;
   },
   //存储dom
   $addItemDiv:$( 'addItemDiv' ),
   $addItemInput:$( 'addItemInput' ),
   $txtTaskTitle:$( 'txtTaskTitle' ),
   $taskItemList:$( 'taskItemList' )
}

其中show()函数和hide()函数均使用了链式调用,每次执行此函数均会返回对象本身,这样对象就可以使用形如类似jQuery书写方式来使用此函数。

然后注册事件:

//.....
//初始化
init: function (){
     /*注册事件*/
     //打开添加文本框
     Tasks.$addItemDiv.addEventListener( 'click' , function (){
         Tasks.show(Tasks.$addItemInput).hide(Tasks.$addItemDiv);
         Tasks.$txtTaskTitle.focus();
     }, true );
     //回车添加
     Tasks.$txtTaskTitle.addEventListener( 'keyup' , function (ev){
         var  ev=ev || window.event;
         if (ev.keyCode==13){
             //TODO:写入本地数据
             Tasks.AppendHtml(task);
             Tasks.$txtTaskTitle.value= '' ;
             Tasks.hide(Tasks.$addItemInput).show(Tasks.$addItemDiv);
         }
         ev.preventDefault();
     }, true );
     //取消
     Tasks.$txtTaskTitle.addEventListener( 'blur' , function (){
         Tasks.$txtTaskTitle.value= '' ;
         Tasks.hide(Tasks.$addItemInput).show(Tasks.$addItemDiv);
     }, true );
     //TODO:初始化数据,加载本地数据,生成html         
},
//....

其中待完成部分为我们下一节将重点计到的html5的本地存储功能。再定义数据操作部分,先写上空白函数:

//....
//增加
Add: function (){
     //TODO
},
//修改
Edit: function (){
     //TODO
},
//删除
Del: function (){
     //TODO
},
//...

还需要初始化此函数使其执行并让匿名函数执行:

( function (){
     var  Tasks = {
//***
     }
     Tasks.init();
})();

好吧,以下就是本节中所要提到的全部代码:

( function (){
     var  $= function (id){ return  document.getElementById(id);}
     var  Tasks = {
         show: function (obj){
             obj.className= '' ;
             return  this ;
         },
         hide: function (obj){
             obj.className= 'hide' ;
             return  this ;
         },
         //存储dom
         $addItemDiv:$( 'addItemDiv' ),
         $addItemInput:$( 'addItemInput' ),
         $txtTaskTitle:$( 'txtTaskTitle' ),
         $taskItemList:$( 'taskItemList' ),
         //初始化
         init: function (){
             /*注册事件*/
             //打开添加文本框
             Tasks.$addItemDiv.addEventListener( 'click' , function (){
                 Tasks.show(Tasks.$addItemInput).hide(Tasks.$addItemDiv);
                 Tasks.$txtTaskTitle.focus();
             }, true );
             //回车添加
             Tasks.$txtTaskTitle.addEventListener( 'keyup' , function (ev){
                 var  ev=ev || window.event;
                 if (ev.keyCode==13){
                     //TODO:写入本地数据
                     Tasks.AppendHtml(Tasks.$txtTaskTitle.value);
                     Tasks.$txtTaskTitle.value= '' ;
                     Tasks.hide(Tasks.$addItemInput).show(Tasks.$addItemDiv);
                 }
                 ev.preventDefault();
             }, true );
             //取消
             Tasks.$txtTaskTitle.addEventListener( 'blur' , function (){
                 Tasks.$txtTaskTitle.value= '' ;
                 Tasks.hide(Tasks.$addItemInput).show(Tasks.$addItemDiv);
             }, true );
             //TODO:初始化数据,加载本地数据,生成html         
         },
         //增加
         Add: function (){
             //TODO
         },
         //修改
         Edit: function (){
             //TODO
         },
         //删除
         Del: function (){
             //TODO
         },
         AppendHtml: function (title){
             var  oDiv=document.createElement( 'div' );
             oDiv.className= 'taskItem' ;
             var  oLabel=document.createElement( 'label' );
             oLabel.className= 'on' ;
             var  oSpan=document.createElement( 'span' );
             oSpan.className= 'taskTitle' ;
             var  oText=document.createTextNode(title);
             oSpan.appendChild(oText);
             oDiv.appendChild(oLabel);
             oDiv.appendChild(oSpan);
             //注册事件
             oDiv.addEventListener( 'click' , function (){
                 //TODO
             }, true );
             Tasks.$taskItemList.appendChild(oDiv); 
         },
         RemoveHtml: function (){
             //TODO
         }
     }
     Tasks.init();
})();
代码中尚未实现的部分,我们将会在下节详细讲解其实现。

手把手教你开发Chrome扩展三:关于本地存储数据

  1. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单
  2. 手把手教你开发Chrome扩展二:为html添加行为
  3. 手把手教你开发Chrome扩展三:关于本地存储数据

HTML5中的localStorage

localStorage与cookie类似,它是存储在客户端浏览器中的数据,它与cookie不同的一点是它没有时间限制。localStorage属于html5中的新特性,在浏览器支持localStorage统计中,Chrome4+、Firefox3.5+、IE8+、IE7兼容模式、Safari4+、Opera10.5+都是支持localStorage的。以下代码可以用于检测你的浏览器是否支持localStorage:

if (window.localStorage){
     alert( '你的浏览器支持localStorage!' );
} else {
     alert( '浏览器不支持localStorage!' );
}

localStorage是以key/value方式来进行存储的,并且value只能是字符串形式,如果你要使用其他数据类型,需要进行相应的转换。设置和获取localStorage方法是使用localStorage.key,或localStorage[key]的形式,如:

localStorage.myName= 'walkingp' ;
localStorage[ 'mySite' ]= 'http://www.cnblogs.com/walkingp' ;
alert( 'name:'  + localStorage.myName + '\rsite:'  + localStorage[ 'mySite' ]);

修改其值就是重新设置相应的localStorage项取值。移除其值可以将其值设为null。

localStorage[ 'mySite' ]= null ;

也可以使用localStorage自带方法getItem()、setItem()和removeItem()来进行相应的获取、设置和移除localStorage项。

localStorage.setItem( 'age' , '24' );
var  age=localStorage.getItem( 'age' );
alert( 'age:'  + age); //age:24
localStorage.removeItem( 'age' );
age=localStorage.getItem( 'age' );
alert( 'age? '  + age); //age? null

可以使用clear()方法来清空所有localStorage。

对于不同域的localStorage,如本地和a.com,两者不影响对方。

关于localStorage本地存储大小,有人测试结果是其他浏览器为5M,Firefox没有作限制。而cookie一般只有几K,可见localStorage非常适合做稍大一些的数据存储,当然对于Chrome等扩展开发是非常合适的。

浏览器中的localStorage管理工具

Chrome和Safari均有自己的本地localStorage查看和管理工具,Firefox拥有第三方插件可以管理localStorage,Chrome中位于开发人员工具中的Resources左侧的Databases(可能稍早一点的版本位于单独出来的工具栏)。我们上面的localStorage在Chrome查看如下,利用这个工具可以修改或者删除相应项。

Safari中需要先在“偏好设置”、“高级”中将“在菜单中显示开发选项”勾选。

开始存储我们的localStorage

以上是我们需要了解的关于localStorage的知识,接下来就是把这个知识应用到我们Chrome扩展中。我们的数据存储分为两个部分,一是每项task需要存储的内容,它是以JSON的形式来存储的,形式如下:

task1:{ "id" :1, "task_item" : "新任务" , "add_time" : "2011-04-04T03:20:34.879Z" , "is_finished" : false }

task1表示key项,后台的JSON表示value项。意义很简单明了,其中is_finished表示当前任务是否已完成。当更新任务状态时就是将此项取值进行相应的更改。

还要放一个指向当前任务的数据,让它充当指针的作用,这样在添加新项时就不需要查询已有task项的id了。

'Tasks:index' :1

下面是我们代码的具体实现,首先开始初始化数据:

var  Tasks = {
     //指针
     index:window.localStorage.getItem( 'Tasks:index' ),
     //初始化
     init: function (){
         if (!Tasks.index){
             window.localStorage.setItem( 'Tasks:index' ,Tasks.index=0);
         }
         //初始化数据
         if (window.localStorage.length-1){
             var  task_list=[];
             var  key;
             for ( var  i=0,len=window.localStorage.length;i<len;i++){
                 key=window.localStorage.key(i);
                 if (/task:\d+/.test(key)){
                     task_list.push(JSON.parse(window.localStorage.getItem(key)));
                 }
             }
             for ( var  i=0,len=task_list.length;i<len;i++){
                 Tasks.AppendHtml(task_list[i]);
             }
         }
     },
//***
}

然后是分别是增加项Add()、修改项Edit()和删除项Del()的方法:

//增加
Add: function (task){
     //更新指针
     window.localStorage.setItem( 'Tasks:index' , ++Tasks.index);
     task.id=Tasks.index;
     window.localStorage.setItem( "task:" + Tasks.index, JSON.stringify(task));
},
//修改
Edit: function (task){
     window.localStorage.setItem( "task:" + task.id, JSON.stringify(task));
},
//删除
Del: function (task){
     window.localStorage.removeItem( "task:" + task.id);
},
//***

其中的JSON.stringify是JSON将Javascript数据结构转换为JSON文本的方法,它与eval()为互操作。详情可见http://json.org/js.html 。

这样我们就将一个简单的Chrome扩展完成了,演示效果图如下:


当然它现在的功能还不够强大,我们还可以对它进行继续扩展,比如任务排序、任务分组、网络存储、定时提醒等。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值