大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ItemSelector重构完结版)

本文主要是介绍大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ItemSelector重构完结版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一,开篇分析

Hi,大家好!大熊君又和大家见面了,还记得上一篇文章吗。主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是

如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式。那么今天这篇文章我们说点什么那?嘿嘿嘿

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

Js部分的代码,如下:

  

 1 function ItemSelector(elem,opts){
 2     this.elem = elem ;
 3     this.opts = opts ;
 4 } ;
 5 var ISProto = ItemSelector.prototype ;
 6 ISProto.getElem = function(){
 7     return this.elem ;
 8 } ;
 9 ISProto.getOpts = function(){
10     return this.opts ;
11 } ;
12 /* data manip*/
13 ISProto._setCurrent = function(current){
14     this.getOpts()["current"] = current ;
15 } ;
16 ISProto.getCurrentValue = function(current){
17     return this.getOpts()["current"] ;
18 } ;
19 /* data manip*/
20 ISProto.init = function(){
21     var that = this ;
22     this.getOpts()["current"] = null ; // 数据游标
23     this._setItemValue(this.getOpts()["currentText"]) ;
24     var itemsElem = that.getElem().find(".content .items") ;
25     this.getElem().find(".title div").on("click",function(){
26         itemsElem.toggle() ;
27     }) ;
28     this.getElem().find(".title span").on("click",function(){
29         itemsElem.toggle() ;
30     }) ;
31     $.each(this.getOpts()["items"],function(i,item){
32         item["id"] = (new Date().getTime()).toString() ;
33         that._render(item) ;
34     }) ;
35 } ;
36 ISProto._setItemValue = function(value){
37     this.getElem().find(".title div").text(value)
38 } ;
39 ISProto._render = function(item){
40     var that = this ;
41     var itemElem = $("<div></div>")
42     .text(item["text"])
43     .attr("id",item["id"]) ;
44     if("0" == item["disabled"]){
45         itemElem.on("click",function(){
46             var onChange = that.getOpts()["change"] ;
47             that.getElem().find(".content .items").hide() ;
48             that._setItemValue(item["text"]) ;
49             that._setCurrent(item) ;
50             onChange && onChange(item) ;
51         })
52         .mouseover(function(){
53             $(this).addClass("item-hover") ;
54         })
55         .mouseout(function(){
56             $(this).removeClass("item-hover") ;
57         }) ;
58     }
59     else{
60         itemElem.css("color","#ccc").on("click",function(){
61             that.getElem().find(".content .items").hide() ;
62             that._setItemValue(item["text"]) ;
63         }) ;
64     }
65     itemElem.appendTo(this.getElem().find(".content .items")) ;
66 } ;

  效果如下图所示:

      

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

    

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

   

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

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

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

  (2),职责划分不清晰

  (3),流程梳理不健全

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

  (1),初始化配置组件

    

 1 $(function(){
 2     var itemSelector = new ItemSelector($("#item-selector"),{
 3         currentText : "Please Choose Item" ,
 4         items : [
 5             {
 6                 text : "JavaScript" ,
 7                 value : "js" ,
 8                 disabled : "1"
 9             } ,
10             {
11                 text : "Css" ,
12                 value : "css" ,
13                 disabled : "0"
14             } ,
15             {
16                 text : "Html" ,
17                 value : "html" ,
18                 disabled : "0"
19             }
20         ] ,
21     }) ;
22     itemSelector.init() ;
23 }) ;

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

 

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

    

 1 ISProto.init = function(){
 2     var that = this ;
 3     this.getOpts()["current"] = null ; // 数据游标
 4     this._setItemValue(this.getOpts()["currentText"]) ;
 5     var itemsElem = that.getElem().find(".content .items") ;
 6     this.getElem().find(".title div").on("click",function(){
 7         itemsElem.toggle() ;
 8     }) ;
 9     this.getElem().find(".title span").on("click",function(){
10         itemsElem.toggle() ;
11     }) ;
12     $.each(this.getOpts()["items"],function(i,item){
13         item["id"] = (new Date().getTime()).toString() ;
14         that._render(item) ;
15     }) ;
16 } ;

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

 

  再继续看渲染部分代码:

  

 1 ISProto._render = function(item){
 2     var that = this ;
 3     var itemElem = $("<div></div>")
 4     .text(item["text"])
 5     .attr("id",item["id"]) ;
 6     if("0" == item["disabled"]){
 7         itemElem.on("click",function(){
 8             var onChange = that.getOpts()["change"] ;
 9             that.getElem().find(".content .items").hide() ;
10             that._setItemValue(item["text"]) ;
11             that._setCurrent(item) ;
12             onChange && onChange(item) ;
13         })
14         .mouseover(function(){
15             $(this).addClass("item-hover") ;
16         })
17         .mouseout(function(){
18             $(this).removeClass("item-hover") ;
19         }) ;
20     }
21     else{
22         itemElem.css("color","#ccc").on("click",function(){
23             that.getElem().find(".content .items").hide() ;
24             that._setItemValue(item["text"]) ;
25         }) ;
26     }
27     itemElem.appendTo(this.getElem().find(".content .items")) ;
28 } ;

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

 

  整个组建的流程包括初始化,渲染(事件绑定),还有就是相关的数据操作方法以及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 !
} ;

 

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

  

1 ISProto._setCurrent = function(){
2    // put you code here !
3 } ;
4 ISProto._getCurrent = function(){
5    // put you code here !
6 } ;

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

 

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

  

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

 

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

转载于:https://www.cnblogs.com/bigbearbb/p/4265028.html

这篇关于大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ItemSelector重构完结版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/237206

相关文章

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求

CSS Anchor Positioning重新定义锚点定位的时代来临(最新推荐)

《CSSAnchorPositioning重新定义锚点定位的时代来临(最新推荐)》CSSAnchorPositioning是一项仍在草案中的新特性,由Chrome125开始提供原生支持需... 目录 css Anchor Positioning:重新定义「锚定定位」的时代来了! 什么是 Anchor Pos

CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比

《CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比》CSS中的position属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布... css 中的 position 属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布局和层叠关

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

全面解析HTML5中Checkbox标签

《全面解析HTML5中Checkbox标签》Checkbox是HTML5中非常重要的表单元素之一,通过合理使用其属性和样式自定义方法,可以为用户提供丰富多样的交互体验,这篇文章给大家介绍HTML5中C... 在html5中,Checkbox(复选框)是一种常用的表单元素,允许用户在一组选项中选择多个项目。本

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.