大熊君JavaScript插件化开发------(第二季)

一,开篇分析

Hi,大家好!大熊君又和大家见面了,还记得昨天的那篇文章吗------这个系列的开篇(第一季)。主要讲述了以“jQuery的方式如何开发插件”,

那么今天我们带着昨天的疑问来继续我们的插件开发之旅。昨天的问题如下:

(1),如果项目技术选型换了这些插件又是强依赖“jQuery”机制,我们以前写的插件将会不能用(假设不用jQuery的情况),如何做重构那?

(2),重构插件的关键逻辑,我们将如何组织那?

好了,带着问题去学习今天的文章吧。

首先我不是否定“jQuery插件的方式”,其次是我们要从不同的角度分析问题,比如说“jQuery插件有如下优点”:

(1),把全部代码放在闭包(一个即时执行函数)里此时闭包相当于一个私有作用域,外部无法访问到内部的信息,并且不会存在全局变量的污染情况。

(2),a) 避免全局依赖;b) 避免第三方破坏;c) 兼容jQuery操作符'$'和'jQuery '。

那我们重构将以什么方式组织代码那,是面向对象的思想(OOP)那?还是过程化的思路进行到底那?还是两者结合设计那?哈哈哈,继续看。。。。。。

 

二,重构昨天的例子

以下是昨天的Js部分源码部分: 

 1 (function($){
 2     $.fn.bigbear = function(opts){
 3         opts = $.extend({},$.fn.bigbear.defaults,opts) ;
 4         return this.each(function(){
 5             var elem = $(this) ;
 6             elem.find("span").text(opts["title"]) ;
 7             $.get(opts["url"],function(data){
 8                 elem.find("div").text(data["text"]) ;
 9             }) ;
10         }) ;
11     } ;
12     $.fn.bigbear.defaults = {
13         title : "这是一个简单的测试" ,
14         url : "data.json"
15     } ;
16 })(jQuery) ;

 我们来逐行分析一下:

  首先确定一下这个插件的功能

  (1),显示我们设置的标题文字信息。

  (2),动态通过异步的方式获取内容信息。

好了!需求明确就好展开讨论了,从上面的代码不难看出逻辑组织很松散,过程化的思维很明显,所以第一步就是把我们的功能需求

以类的方式有效地组织起来。看如下重构后的代码:

  

 1 $(function(){
 2     $("#bb").bigbear() ;
 3 }) ;
 4 (function($){
 5     $.fn.bigbear = function(opts){
 6         opts = $.extend({},$.fn.bigbear.defaults,opts) ;
 7         return this.each(function(){
 8             var elem = $(this) ;
 9             var bb = new BigBear(elem,opts) ;
10             bb.getElem().trigger("data") ;
11         }) ;
12     } ;
13     $.fn.bigbear.defaults = {
14         title : "这是一个简单的测试" ,
15         url : "data.json"
16     } ;
17 })(jQuery) ;
18 
19 function BigBear(elem,opts){
20     this.elem = elem ;
21     this.opts = opts ;
22     this.init() ;
23 } ;
24 var bbProto = BigBear.prototype ;
25 bbProto.getElem = function(){
26     return this.elem ;
27 } ;
28 bbProto.getOpts = function(){
29     return this.opts ;
30 } ;
31 bbProto.init = function(){
32     var that = this ;
33     this.getElem().on("data",function(){
34         that._setTitle(that.getOpts()["title"]) ;
35         $.get(that.getOpts()["url"],function(result){
36             that.getElem().find("div").text(result["text"]) ;
37         }) ;
38     }) ;
39 } ;
40 bbProto._setTitle = function(text){
41     this.getElem().find("span").text(text) ;
42 } ;

  哈哈哈,是不是代码多了不少,其实这种方式就是面向对象的角度看问题,先去分析功能需求,然后设计我们的类,虽然说我们不可能一下设计得很出色,

但是看问题角度改变了,我们的代码可读性强了,以及更好地进行维护这样我们的目的也就达到了。

  以下是是摘自“Bootstrap”Js部分的相关源码实现,如下图:

  

 

不难看出也是相似的实现方式,通过类来维护我们插件的主要逻辑。

 

(三),增加新功能,引出额外的类

  现在需求增加了,需要在体验上有所变化,加载数据时有“loading”效果。

  实现思路可以这样,在原始的内容区把文字设置成“装载数据中。。。。”的字样,然后引入一个新的类,如下:

  

1 function Overlay(){
2 
3 } ;
4 var olProto = Overlay.prototype ;
5 olProto.show = function(){} ;
6 olProto.hide = function(){} ;
7 // 具体实现就不写了

 

  好了,遮罩层已经有了,现在我们怎么集成进来那?我们用组合的方式接入进来,如下:

 

 1 function BigBear(elem,opts){
 2     this.elem = elem ;
 3     this.opts = opts ;
 4     this.overlay = new Overlay() ;
 5     this.init() ;
 6 } ;
 7 var bbProto = BigBear.prototype ;
 8 bbProto.getElem = function(){
 9     return this.elem ;
10 } ;
11 bbProto.getOpts = function(){
12     return this.opts ;
13 } ;
14 bbProto.init = function(){
15     var that = this ;
16     var loadingText = "数据装载中。。。" ;
17     this.getElem().on("data",function(){
18         that._setTitle(that.getOpts()["title"]) ;
19         that.overlay.show() ;
20         that.getElem().find("div").text(loadingText) ;
21         $.get(that.getOpts()["url"],function(result){
22             that.overlay.hide() ;
23             that.getElem().find("div").text(result["text"]) ;
24         }) ;
25     }) ;
26 } ;
27 bbProto._setTitle = function(text){
28     this.getElem().find("span").text(text) ;
29 } ;

 

  到此只为我们的功能就算是结束了,这样写的插件,我相信比第一个版本好很多,当然这不是最优的实现,需要从细节上不断重构,但是这种方式是一种可选的开发插件的方式。

 

  以下是完整的代码

  

 1 $(function(){
 2     $("#bb").bigbear() ;
 3 }) ;
 4 (function($){
 5     $.fn.bigbear = function(opts){
 6         opts = $.extend({},$.fn.bigbear.defaults,opts) ;
 7         return this.each(function(){
 8             var elem = $(this) ;
 9             var bb = new BigBear(elem,opts) ;
10             bb.getElem().trigger("data") ;
11         }) ;
12     } ;
13     $.fn.bigbear.defaults = {
14         title : "这是一个简单的测试" ,
15         url : "data.json"
16     } ;
17 })(jQuery) ;
18 
19 function BigBear(elem,opts){
20     this.elem = elem ;
21     this.opts = opts ;
22     this.overlay = new Overlay() ;
23     this.init() ;
24 } ;
25 var bbProto = BigBear.prototype ;
26 bbProto.getElem = function(){
27     return this.elem ;
28 } ;
29 bbProto.getOpts = function(){
30     return this.opts ;
31 } ;
32 bbProto.init = function(){
33     var that = this ;
34     var loadingText = "数据装载中。。。" ;
35     this.getElem().on("data",function(){
36         that._setTitle(that.getOpts()["title"]) ;
37         that.overlay.show() ;
38         that.getElem().find("div").text(loadingText) ;
39         $.get(that.getOpts()["url"],function(result){
40             that.overlay.hide() ;
41             that.getElem().find("div").text(result["text"]) ;
42         }) ;
43     }) ;
44 } ;
45 bbProto._setTitle = function(text){
46     this.getElem().find("span").text(text) ;
47 } ;
48 
49 function Overlay(){
50 
51 } ;
52 var olProto = Overlay.prototype ;
53 olProto.show = function(){} ;
54 olProto.hide = function(){} ;
55 // 具体实现就不写了

 

 

(四),最后总结

  (1),面向对象的思考方式合理分析功能需求。

  (2),以类的方式来组织我们的插件逻辑。

  (3),不断重构上面的实例,最好自己写一下,并且完善“Overlay”的逻辑。

  (4),大家学习完继续思考一下,如何进行合理的重构那?不要设计过度,要游刃有余,推荐的方式是过程化设计与面向对象思想设计相结合。

 

 

 

                   哈哈哈,本篇结束,未完待续,希望和大家多多交流够沟通,共同进步。。。。。。呼呼呼……(*^__^*)                       

posted @ 2015-01-21 16:37  大熊君Bigbear  阅读(3413)  评论(29编辑  收藏  举报