JavaScript插件化开发教程(六)

一,开篇分析

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

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 = $("

.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")) ;

} ;

效果如下图所示:

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

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

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

大家从代码不难看出,已经通过“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 = $("

.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 = $("

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多选模式,现在只是默认下拉模式。

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

PHP实现长文章分页实例代码(附源码)

如何解决在jsp页面上导入.xls文件报错问题

php操作memcache缓存方法分享

详解Java设计模式编程中的中介者模式

C++读取INI配置文件类实例详解

Javascript模块化编程详解

centos6.5中安装mongodb简明总结

Win10 Mobile将迎来原生的Windows10通知同步功能

SMTP客户端未通过身份验证等多种错误解决方案分享

Win10 TH2预览版10586桌面水印消失怎么办?预览版需重注册

win10系统字体显示正常但是第三方软件字体模糊该怎么办?

gridview 行选添加颜色和事件

静态gb2312编码在项目传值出现中文乱码现象

已安装KB3035583补丁却没有获取Win10预订图标的解决方法

php 插件化开发模式,JavaScript_JavaScript插件化开发教程(六),一,开篇分析 今天这篇文章 - phpStudy...相关推荐

  1. android开发模式之插件化开发

    一.简介 插件化开发是将整个app拆分成很多模块,这些模块包括一个宿主和多个插件,每个模块都是一个apk(组件化的每个模块是个lib),最终打包的时候将宿主apk和插件apk分开或者联合打包.由宿主A ...

  2. java分层开发模式的概念_Java开发人员的z / OS概念

    简介:大型机2.0? 我从未使用过打Kong卡或3480磁带设备. 我不是大型机一代的一员 . 但是,我在信息技术(IT)生涯的早期就曾在大型机商店工作. 我是互联网专家,大型机系统程序员将我带入了翅 ...

  3. devops开发模式流程图_2020 Web开发人员路线图–成为前端,后端或DevOps开发人员的视觉指南

    devops开发模式流程图 There are many ways you can go about picking up the skills you need to become a develo ...

  4. java 开发模式详解_Java开发中的23种设计模式详解4

    其实每个设计模式都是很重要的一种思想,看上去很熟,其实是因为我们在学到的东西中都有涉及,尽管有时我们并不知道,其实在Java本身的设计之中处处都有体现,像AWT.JDBC.集合类.IO管道或者是Web ...

  5. Hybrid APP 混合开发模式的选择之路(六:JSBridge---Native代码与JS代码的通信桥梁)

    原文出处:http://www.cnblogs.com/dailc/p/5931324.html JSBridge是Native代码与JS代码的通信桥梁.目前的一种统一方案是:H5触发url sche ...

  6. .NET简谈插件系统开发模式

    今天跟大家分享一下我们在日常开发中并不常用的开发模式"插件系统模式",什么叫插件从大一点的概念讲就是我们开发的软件是由很小的模块组成,每一块都能成功的装卸,使我们的软件成为一个有机 ...

  7. 企业移动信息化应用开发模式选型指南

    随着移动互联网的逐步深入,移动应用已经从新闻.搜索.电商.游戏.视频等热门应用逐步向企业移动应用领域转移.而且市场规模逐年增长,据IDC发布的报告显示,2013年中国企业级移动应用市场规模为9.3亿美 ...

  8. App原生、混合、纯WEB开发模式的优劣分析

    什么叫做原生App? 什么是混合app? 什么是Web App开发? Native App开发即我们所称的传统APP开发模式(原生APP开发模式),该开发针对IOS.Android等不同的手机操作系统 ...

  9. APP系统开发模式一共有哪几种?

    App的开发基于硬件设备所运行的操作系统,现在主流的移动操作系统有苹果的iOS.google 的Android和微软的Windows Phone 8 等,主要通过运行应用的硬件和设备的其他系统约束来区 ...

最新文章

  1. 在线分析|在线做随机森林分析
  2. python 装饰器 参数-如何将额外的参数传递给Python装饰器?
  3. Python常用的模块的使用技巧
  4. springboot主要注解及其作用
  5. java中rank函数_sql rank()函数
  6. 轻量级的jQuery表单校验插件: Happy.js
  7. 注册表使用次数修改_如何使用系统注册表编辑器来优化电脑系统
  8. WritableComparable排序的使用案例
  9. 什么是动作分析?动作分析的方法有哪些?
  10. 计算机应用202001常规,2001年4月份全国高等教育自学考试计算机应用基础试题
  11. poe摄像头与服务器连接系统图,PoE监控系统的4种连接方式!
  12. 干货分享!一份你不知道的武汉Web前端开发学习攻略
  13. x64dbg 自带脚本系统
  14. uboot网口调试Marvell phy 88E1111
  15. ECAM6--变量与函数
  16. JavaFX、计算器
  17. QEMU文档之虚拟NVDIMM
  18. 锥,凸锥,二阶锥,二阶锥规划
  19. Javascript Flash harness
  20. android根据url加载图片路径,初学Android——通过URL加载图片

热门文章

  1. Flash 第十章 补间动画复习和引导动画
  2. 浅谈项目建议书、可行性研究、项目评估、项目后评价的作用及其区别
  3. bcd转ascii码 流程图_BCD码转换成二进制和ASCII码
  4. Linux操作系统命令复习
  5. 编写javascript_编写javascript和打字稿时的一些最佳快捷方式
  6. MathType编辑钢筋符号就是这么简单
  7. java CSAE 的穿透
  8. C语言按键控制喇叭,Windows环境下C语言控制你的PC喇叭(PC Speaker)编程
  9. Arduino UNO AT24C32进行字符串数据读写操作(二)
  10. 对于PTA exercise 3-3 Write a function expand(s1,s2) 问题的一种解法与思考