JavaScript插件化开发教程(六)


Posted in Javascript onFebruary 01, 2015

一,开篇分析

今天这篇文章我们说点什么那?嘿嘿嘿。我们接着上篇文章对不足的地方进行重构,以深入浅出的方式来逐步分析,让大家有一个循序渐进提高的过程。废话少说,进入正题。让我们先来回顾一下之前的

Js部分的代码,如下:

 function ItemSelector(elem,opts){

     this.elem = elem ;

     this.opts = opts ;

 } ;

 var ISProto = ItemSelector.prototype ;

 ISProto.getElem = function(){

     return this.elem ;

 } ;

 ISProto.getOpts = function(){

     return this.opts ;

 } ;

 /* data manip*/

 ISProto._setCurrent = function(current){

     this.getOpts()["current"] = current ;

 } ;

 ISProto.getCurrentValue = function(current){

     return this.getOpts()["current"] ;

 } ;

 /* data manip*/

 ISProto.init = function(){

     var that = this ;

     this.getOpts()["current"] = null ; // 数据游标

     this._setItemValue(this.getOpts()["currentText"]) ;

     var itemsElem = that.getElem().find(".content .items") ;

     this.getElem().find(".title div").on("click",function(){

         itemsElem.toggle() ;

     }) ;

     this.getElem().find(".title span").on("click",function(){

         itemsElem.toggle() ;

     }) ;

     $.each(this.getOpts()["items"],function(i,item){

         item["id"] = (new Date().getTime()).toString() ;

         that._render(item) ;

     }) ;

 } ;

 ISProto._setItemValue = function(value){

     this.getElem().find(".title div").text(value)

 } ;

 ISProto._render = function(item){

     var that = this ;

     var itemElem = $("<div></div>")

     .text(item["text"])

     .attr("id",item["id"]) ;

     if("0" == item["disabled"]){

         itemElem.on("click",function(){

             var onChange = that.getOpts()["change"] ;

             that.getElem().find(".content .items").hide() ;

             that._setItemValue(item["text"]) ;

             that._setCurrent(item) ;

             onChange && onChange(item) ;

         })

         .mouseover(function(){

             $(this).addClass("item-hover") ;

         })

         .mouseout(function(){

             $(this).removeClass("item-hover") ;

         }) ;

     }

     else{

         itemElem.css("color","#ccc").on("click",function(){

             that.getElem().find(".content .items").hide() ;

             that._setItemValue(item["text"]) ;

         }) ;

     }

     itemElem.appendTo(this.getElem().find(".content .items")) ;

 } ;

效果如下图所示:

JavaScript插件化开发教程(六)

a)------非可操作状态

JavaScript插件化开发教程(六)

b)------可操作状态

JavaScript插件化开发教程(六)

(二),打开思路,进行重构

大家从代码不难看出,已经通过“Js”中的语法特性,以面向对象的方式进行了有效的组织,比松散的过程化形式的组织方式好多了,但是仍然会发现有很多不足的地方。

(1),里面重复代码太多

(2),职责划分不清晰

(3),流程梳理不健全

我们基于以上几点进行有效的重构,我们首先要梳理一下这个组件的需求,功能点如下:

(1),初始化配置组件

 $(function(){

     var itemSelector = new ItemSelector($("#item-selector"),{

         currentText : "Please Choose Item" ,

         items : [

             {

                 text : "JavaScript" ,

                 value : "js" ,

                 disabled : "1"

             } ,

             {

                 text : "Css" ,

                 value : "css" ,

                 disabled : "0"

             } ,

             {

                 text : "Html" ,

                 value : "html" ,

                 disabled : "0"

             }

         ] ,

     }) ;

     itemSelector.init() ;

 }) ;

这块代码很清晰,不需要做任何修改,但是大家可以基于以上配置扩展功能,比如增加配置项“mode”支持多种选项方式。如:“checkbox勾选模式”。

接下来是要完成初始化逻辑,如下:

 ISProto.init = function(){

     var that = this ;

     this.getOpts()["current"] = null ; // 数据游标

     this._setItemValue(this.getOpts()["currentText"]) ;

     var itemsElem = that.getElem().find(".content .items") ;

     this.getElem().find(".title div").on("click",function(){

         itemsElem.toggle() ;

     }) ;

     this.getElem().find(".title span").on("click",function(){

         itemsElem.toggle() ;

     }) ;

     $.each(this.getOpts()["items"],function(i,item){

         item["id"] = (new Date().getTime()).toString() ;

         that._render(item) ;

     }) ;

 } ;

这段代码问题很多,职责不明确,初始化逻辑包含了功能点的细节实现。

再继续看渲染部分代码:

 ISProto._render = function(item){

     var that = this ;

     var itemElem = $("<div></div>")

     .text(item["text"])

     .attr("id",item["id"]) ;

     if("0" == item["disabled"]){

         itemElem.on("click",function(){

             var onChange = that.getOpts()["change"] ;

             that.getElem().find(".content .items").hide() ;

             that._setItemValue(item["text"]) ;

             that._setCurrent(item) ;

             onChange && onChange(item) ;

         })

         .mouseover(function(){

             $(this).addClass("item-hover") ;

         })

         .mouseout(function(){

             $(this).removeClass("item-hover") ;

         }) ;

     }

     else{

         itemElem.css("color","#ccc").on("click",function(){

             that.getElem().find(".content .items").hide() ;

             that._setItemValue(item["text"]) ;

         }) ;

     }

     itemElem.appendTo(this.getElem().find(".content .items")) ;

 } ;

问题很明显,发现了重复性的操作,应该进行合理的抽象,已达到复用的目的。

整个组建的流程包括初始化,渲染(事件绑定),还有就是相关的数据操作方法以及dom操作的辅助方法。

综上所述,经过简单的梳理后,我们应该建立起功能的操作目的以及流程主线的任务分配,各负其责。

所以我们重构的目的很明确了,对!就是进行功能点的抽象,友好的职责划分,那么我们如何实现那?

第一步,建立流程功能方法:(方法接口)

ISProto.init = function(){

   // put you code here !

} ;

ISProto._render = function(){

   // put you code here !

} ;

 第二部,建立抽象后的方法接口:

ISProto._fnItemSelectorDelegateHandler = function(){

   // put you code here !

} ;

ISProto._fnTriggerHandler = function(){

   // put you code here !

} ;

ISProto._addOrRemoveClass = function(){

   // put you code here !

} ;

第三步,建立数据操作接口:

 ISProto._setCurrent = function(){

    // put you code here !

 } ;

 ISProto._getCurrent = function(){

    // put you code here !

 } ;

还有一些参照下面的完整源码,这里只是说的思路。

(三),完整代码以供学习,本代码已经过测试

function ItemSelector(elem,opts){

    this.elem = elem ;

    this.opts = opts ;

    this.current = -1 ; // 数据游标

} ;

var ISProto = ItemSelector.prototype ;

/* getter api*/

ISProto.getElem = function(){

    return this.elem ;

} ;

ISProto.getOpts = function(){

    return this.opts ;

} ;

ISProto._getCurrent = function(){

    return this.current ;

} ;

/* getter api*/

/* data manip*/

ISProto._setCurrent = function(current){

    this.current = current ;

} ;

ISProto._setItemText = function(text){

    this.getElem().find(".title div").text(text) ;

} ;

/* data manip*/

 

/* update on 2015 1/31 23:38 */

ISProto._fnTriggerHandler = function(index,text,value){

    if(this._isDisabled(value)){

        index = -1 ;

        text = this.getOpts()["currentText"] ;

    }

    this._setItemText(text) ;

    this._setCurrent(index) ;

    this.getElem().find(".content .items").hide() ;

} ;

ISProto._addOrRemoveClass = function(elem,className,addIs){

    if(addIs){

        elem.addClass(className) ;

    }

    else{

        elem.removeClass(className) ;

    }

} ;

ISProto._fnItemSelectorDelegateHandler = function(){

    var that = this ;

    this.getElem().on("click","[data-toggle]",function(){

        that.getElem().find(".content .items").toggle() ;

    }) ;

} ;

ISProto._isDisabled = function(value){

    return ("1" == value) ? true : false ;

} ;

/* update on 2015 1/31 23:38 */

ISProto.init = function(){

    var that = this ;

    this._fnItemSelectorDelegateHandler() ;

    $.each(this.getOpts()["items"],function(i,item){

        item["index"] = i ;

        that._render(item) ;

    }) ;

    this._fnTriggerHandler(this._getCurrent(),this.getOpts()["currentText"],"1") ;

} ;

ISProto._render = function(item){

    var that = this ;

    var itemElem = $("<div></div>").text(item["text"]).attr("id",item["index"]) ;

    var activeClass = ("0" == item["disabled"]) ? "item-hover" : "item-disabled-hover" ;

    itemElem.on("click",function(){

        that._fnTriggerHandler(item["index"],item["text"],item["disabled"]) ;

    })

    .mouseover(function(){

        that._addOrRemoveClass($(this),activeClass,true) ;

    })

    .mouseout(function(){

        that._addOrRemoveClass($(this),activeClass,false) ;

    }) ;

    itemElem.appendTo(this.getElem().find(".content .items")) ;

} ;

(四),最后总结

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

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

(3),不断重构上面的实例,如何进行合理的重构那?不要设计过度,要游刃有余,推荐的方式是过程化设计与面向对象思想设计相结合。

    (4),下篇文章中会扩展相关功能,比如“mode”这个属性,为"1"时支持checkbox多选模式,现在只是默认下拉模式。

看我本文,是不是要比上一篇代码优秀了很多呢,小伙伴们自己做项目也应该多想多做,尽量使自己的代码更加的合理。

Javascript 相关文章推荐
javascript模拟实现C# String.format函数功能代码
Nov 25 Javascript
javascript:json数据的页面绑定示例代码
Jan 26 Javascript
原生JS实现美图瀑布流布局赏析
Sep 07 Javascript
详解JavaScript中localStorage使用要点
Jan 13 Javascript
浅谈js中的引用和复制(传值和传址)
Sep 18 Javascript
Vue.js实现无限加载与分页功能开发
Nov 03 Javascript
Node.js复制文件的方法示例
Dec 29 Javascript
vue2中使用sass并配置全局的sass样式变量的方法
Sep 04 Javascript
详解react native页面间传递数据的几种方式
Nov 07 Javascript
抖音上用记事本编写爱心小程序教程
Apr 17 Javascript
Vue中的this.$options.data()和this.$data用法说明
Jul 26 Javascript
CentOS 8.2服务器上安装最新版Node.js的方法
Dec 16 Javascript
JavaScript插件化开发教程(五)
Feb 01 #Javascript
对JavaScript中this指针的新理解分享
Jan 31 #Javascript
IE下支持文本框和密码框placeholder效果的JQuery插件分享
Jan 31 #Javascript
有效提高JavaScript执行效率的几点知识
Jan 31 #Javascript
JavaScript日期时间与时间戳的转换函数分享
Jan 31 #Javascript
JavaScript监听和禁用浏览器回车事件实例
Jan 31 #Javascript
JavaScript编程中容易出BUG的几点小知识
Jan 31 #Javascript
You might like
php通过文件流方式复制文件的方法
2015/03/13 PHP
php动态函数调用方法
2015/05/21 PHP
如何在PHP中使用AES加密算法加密数据
2020/06/24 PHP
非阻塞动态加载javascript广告实现代码
2010/11/17 Javascript
js实现的仿新浪微博完美的时间组件升级版
2011/12/20 Javascript
js中substring和substr的定义和用法
2014/05/05 Javascript
jquery重复提交请求的原因浅析
2014/05/23 Javascript
jQuery中ajax和post处理json的不同示例对比
2014/11/02 Javascript
jQuery+ajax中getJSON() 用法实例
2014/12/22 Javascript
Express + Session 实现登录验证功能
2017/09/08 Javascript
JS库之wow.js使用方法
2017/09/14 Javascript
使用html+js+css 实现页面轮播图效果(实例讲解)
2017/09/21 Javascript
Node.JS段点续传:Nginx配置文件分段下载功能的实现方法
2018/03/12 Javascript
vue axios请求超时的正确处理方法
2018/04/02 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
JS实现判断有效的数独算法示例
2019/02/25 Javascript
js实现列表向上无限滚动
2020/01/13 Javascript
JS面向对象实现飞机大战
2020/08/26 Javascript
[37:37]DAC2018 4.4 淘汰赛 Optic vs Mineski 第二场
2018/04/05 DOTA
python遍历文件夹,指定遍历深度与忽略目录的方法
2018/07/11 Python
Flask Web开发入门之文件上传(八)
2018/08/17 Python
Django uwsgi Nginx 的生产环境部署详解
2019/02/02 Python
python base64库给用户名或密码加密的流程
2020/01/02 Python
详解基于Jupyter notebooks采用sklearn库实现多元回归方程编程
2020/03/25 Python
美国地毯购买网站:Rugs USA
2019/02/23 全球购物
新闻系毕业生推荐信
2013/11/16 职场文书
生物技术专业毕业生求职信范文
2013/12/14 职场文书
幼儿园教师国培感言
2014/02/02 职场文书
大学生安全责任书
2014/07/25 职场文书
革命英雄事迹演讲稿
2014/09/13 职场文书
2014年人事部工作总结
2014/12/03 职场文书
联村联户简报
2015/07/21 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
慰问信(范文3篇)
2019/10/23 职场文书
Python超详细分步解析随机漫步
2022/03/17 Python
Ubuntu18.04下QT开发Android无法连接设备问题解决实现
2022/06/01 Java/Android