zoukankan      html  css  js  c++  java
  • JavaScript插件化开发

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

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

     
  • 相关阅读:
    基于注解的ssh框架之spring配置文件
    hdu 4770 Lights Against Dudely
    便捷开发工具(未完)
    solr 简单搭建 数据库数据同步(待续)
    Nginx对某个文件夹或整个站点进行登录认证的方法
    swift 单例模式
    POJ 2823 Sliding Window(单调队列)
    Android 网络下载图片
    一个表空间offline后alert日志报ORA-01135 和ORA-01110的问题
    [c#]分析器错误消息: 发现不明白的匹配。
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4240390.html
Copyright © 2011-2022 走看看