使用Dijit实现界面组“.NET研究”件化开发

  对于组件化的软件工程设计,很多开发人员都比较熟悉。组件化的设计适合于复杂的软件系统和团队协作开发。把软件系统划分成若干个组件,组件之间通过预先定义好的接口和协议进行通讯和协作,共同完成整个软件系统的职责。团队中的开发人员可以各自负责不同的组件。组件化的思想在桌面应用和Web应用后台开发中比较流行,相关的技术和实践都比较成熟。

  而在Web应用的前端部分,组件化一直进展得比较缓慢。这其中的原因有很多,最主要的是Web应用的前端在开始的时候比较简单,没有组件化和设计的必要。随着Ajax应用的流行,Web前端部分越发复杂,用户对Web应用的要求不断向桌面应用靠拢。HTML语言的基本界面元素不能单独地满足这样的需求。菜单、树形控件、对话框和进度条等组件,在现在的Ajax应用中十分常见,但是并不是HTML默认提供的。HTML 5规范中引入了一些新的元素,但还是不够。组件化对于Web应用本身的代码共享和团队分工也是很有意义的。

  Web 应用前端组件化的发展也是渐进的。开始的时候,只是一些简单的HTML、CSS加上JavaScript的代码示例。比如当需要实现一个多级菜单的时候,就下载相关的代码示例,就根据自己的需要进行修改。这样的组件比较难以复用。后来JavaScript框架开始流行的时候,有些框架本身就提供了组件的支持,包括Ext JS、jQuery UI和Dojo等。不过不同框架提供的组件模型不尽相同。

  Dijit组件模型概述

  Web 应用的前端组件的定义比较宽泛。一个组件占据Web页面上的某个区域,并负责完成某项具体的任务。Web组件有时候也被称为小部件(widget)。在 Dijit组件模型中,一个Dijit组件是一个JavaScript类,可以在页面上通过new操作符来创建组件的实例。每个组件实例都需要与页面上的某个DOM元素绑定在一起。这个DOM元素就是该组件的根节点。在Dijit组件的逻辑中,就可以对该根节点进行操纵来构建用户界面。组件 JavaScript类暴露出来的属性和方法就是该组件的接口。

  Dijit组件的使用

  Dijit 组件的使用方式非常简单。首先需要在页面上加载组件的JavaScript代码,这通过dojo.require函数就可以完成。接着在页面上找到或创建一个DOM元素作为该组件的根节点。最后通过new操作符创建即可。如new dijit.form.ComboBox({}, node)就可以用node作为根元素创建一个dijit.form.ComboBox组件,即一个下拉列表选择框。可以看到创建Dijit组件的时候,使用了两个参数:第二个参数是组件的根元素,如果创建的时候不指定该根元素,会自动创建一个新的DIV元素作为根元素。

  不过该新创建的根元素一般没有加入到当前的文档树中,可以通过组件的placeAt方法来设置该组件在页面文档树中的位置。第一个元素则是一个JavaScript对象,包含了组件的配置属性。通常来说,一个Dijit组件是可以复用的。因此一般都会提供一些属性供使用者进行配置。通过这个参数,就可以修改这些配置。

  上面提到的是程序式的方式创建Dijit组件,还有另外的一种方式来进行创建,即通过在HTML代码中以声明式的方式创建,如


<div dojoType="dijit.Dialog" id="myDialog" title="示例对话框">
<h3>对话框标题上海闵行企业网站设计与制作</h3>
<div>对话框内容</div>
</div>

  声明式的方式在一定程度上简化了开发人员使用Dijit组件的方式。声明式的方式与编写HTML代码的形式类似,只需要在一般的HTML元素上添加一些额外的属性就可以把HTML片段转换成Dijit组件。这对于只熟悉HTML语言的人来说非常方便,相当于在HTML语言的基本元素之上,增加了更多的可用组件。

  Dijit深入分析

  Dijit组件基本类

  所有的Dijit组件都继承自dijit._Widget类。dijit._Widget类中定义了与组件相关的一系列方法。这些方法中有一些是与组件生命周期相关的,有一些则是所有组件都需要的通用方法。了解Dijit组件的生命周期有利于理解Dijit组件的运行方式,从而更好的使用已有的组件或开发出自己的组件。

  创建Dijit组件的过程开始于dijit._Widget类中的create方法。create方法采用了典型的模板方法设计模式,即在该方法中封装了创建组件的基本流程。该方法会执行一些重要的操作,并依次调用其它的方法来完成整个创建过程。具体的流程包括:

  • 把创建时的配置参数混入(mix-in)到组件中。比如在创建组件的时候使用的方式是var myWidget = new TestWidget({prop : "Hello"}, node);,那么在创建完成之后就可以通过myWidget.prop来获取到"Hello",在组件中也可以通过this.prop来访问。
  • 调用生命周期方法:postMixInProperties。该方法在配置参数混入之后调用,可以对混入的参数进行修改。
  • 把该新创建出来的组件添加到全局的组件对象注册表中。Dijit组件都会被分配一个惟一的标识符。添加到注册表中之后,就可以用dijit.byId来根据标识符获取组件对象。上海徐汇企业网站制作i>
  • 调用生命周期方法:buildRendering。该方法用来完成构建组件的用户界面。该方法负责设置this.domNode的值,表示的是创建完成的组件的根元素。
  • 调用生命周期方法:postCreate。该方法在用户界面构建完成之后被调用。一般是组件内部行为逻辑的起点,类似HTML页面中的onload方法。

  对于Dijit组件开发人员来说,创建一个新的Dijit非常简单。只需要用dojo.declare声明一个JavaScript类并继承自 dijit._Widget,在该类中覆写感兴趣的JavaScript方法即可。最简单的情况是覆写postCreate方法并添加组件的逻辑。

  对于用来包含其它子组件的容器类组件来说,一般会覆写startup方法来让其调用者显式的启动这个组件。这是因为在postCreate被调用的时上海网站建设候,只是保证了组件的DOM节点已经被创建成功了,但是这些DOM节点可能并没有被添加到当前文档树中,因此不能在postCreate中包含与DOM节点大小和位置相关的代码。如果要添加这样的代码,应该在startup中添加。很多容器类组件都使用该方法来对其子节点进行布局。

  使用HTML模板

  如果只是使用dijit._Widget的话,编写Dijit组件会比较繁琐。比如在构建用户界面的时候,可能会需要很多的DOM操作,编写起来也不方便。 Dijit提供了dijit._Templated用来使用HTML片段来定义组件的内容。HTML片段是作为组件的内容模板。如:


dojo.declare("TempWidget", [dijit._Widget, dijit._Templated], {
templateString : "<div><span>Hello</span></div>"
});

  TempWidget继承了两个JavaScript类,除了必需的dijit._Widget之外,还有dijit._Templated的。需要保证 dijit._Widget是父类数组的第一个元素,只有它是真正意义上的父类,其余的是混入类。dijit._Templated类已经覆写了 buildRendering方法来从HTML模板中创建组件内容的DOM元素,并作为组件的this.domNode的值。在HTML模板中,除了可以使用基本的HTML元素和属性之外,还有一些附加的实用功能:

  • 在HTML模板中直接引用组件中的属性。比如组件中有个属性叫title,在HTML模板中想引用该属性的值,可以直接写<span>${title}</span>。如果属性title的值是"Hello",那么上述模板在运行时刻会变成<span>Hello</span>。
  • 通过dojoAttachPoint来声明在组件对象中可见的DOM节点。当需要在组件中引用某个内部的DOM节点时,不需要再次进行查询,通过 dojoAttachPoint即可。如声明<div><span dojoAttachPoint="myNode"></span></div>,就可以在组件对象中通过 this.myNode来引用该SPAN元素。
  • 通过dojoAttachEvent来进行事件绑定。这种方式比先手工查询D上海闵行企业网站制作OM节点,再通过dojo.connect来绑定要简单得多。如声明<div><button dojoAttachEvent="onclick:test">Test</button></div>,就意味着将组件的test方法绑定到按钮的onclick事件上。

  dijit._Templated的模板机制的这些实用功能减少了构建用户界面时的一些繁琐代码。

  作为容器

  如果组件是作为其它组件的容器来使用的话,就可以混入dijit._Container类。该类提供了对子组件的基本管理功能,包括查询、添加和删除等。使用该类的时候,需要在组件中声明一个containerNode的属性作为子组件的父节点。创建出Dijit组件之后,就可以通过addChild方法来添加子组件了。

  销毁过程

  组件在创建并运行之后,就可能需要被销毁。销毁一个Dijit组件很简单,只需要调用destroyRecursive方法即可。该方法会负责销毁当前Dijit组件及其包含的子组件。当一个组件被销毁的时候,其uninitialize方法会被调用,类似于析构函数。因此可以把组件特有的销毁逻辑添加在uninitialize方法中。

  Dijit组件的接口与交互

  前面提到,组件之间通过设计好的接口和协议进行通讯。对于Dijit组件来说,它所提供的接口一般有下面这几类:

  • 公开的属性和方法上海企业网站制作。这些属性和方法类似于Java类中的公开的域和方法,在获取到组件对象之后可以直接使用。
  • 通过dojo.connect进行连接。有些组件提供了一些占位符方法用来允许其使用者监听其内部状态的变化,类似于DOM事件的处理。

  当组件之间进行通讯和协作的时候,一般有下面几种交互的模式:

  • 传递组件对象的引用。这种做法一般是在创建新组件的时候,将其需要引用的组件对象传递进去,如var anotherWidget = new MyWidget({parent : oneWidget}, node);。
  • 不传递对象引用,而是进行查找。这种情况适用于所依赖的组件的ID已知的情况。可以通过dijit.byId来直接进行查找。
  • 使用Dojo提供的全局通讯机制:dojo.publish和dojo.subscribe。一个组件通过dojo.publish来发布消息,另外一个组件则通过dojo.subscribe来监听相关的消息并做出处理。

  一般来说,比较推荐的做法是第一种,即通过传递组件对象的引用来完成。不过当组件之间的关系比较复杂的时候,有可能需要将一个对象的引用进行多次传递。这个时候也可以考虑后两种做法。

  Dijit开发最佳实践

  编写Dijit组件并不是一件复杂的事情,只需要按照一般的流程依次完成即可。不过Dijit组件本身的设计和实现比较复杂,包含了比较多的内容。下面对一些重点的地方进行讨论。

  编程式和声明式的创建方式选择

  这两种方式的区别只是在于开发人员的使用方式上。用声明式方式声明的Dijit组件,在运行时刻也是通过程序式的方式来进行创建的,由dojo.parser.parse方法来完成。因此,声明式的方式更像一种语法糖衣。不过声明式方式的一个好处是可以实现优雅地退化(graceful degradation),即当JavaScript不被支持的时候,仍然可以在页面上显示出部分内容。

  对于简单的和容器类的组件来说,声明式创建的方式比较好。简单的组件用声明式的方式比较简洁。而容器类的组件在创建的时候一般都需要指定所包含的内容。使用声明式的时候,组件的子节点会自动作为容器类组件的子组件来添加。而如果以程序式的方式来完成的话,需要手工创建子组件,并通过addChild方法来逐个添加。代码会比较繁琐。

  组件状态变迁与外观样式

  在开发Dijit组件中,经常会遇到的一个场景是根据组件内部的状态变化改变其外观样式。比如对于一个单选按钮组件来说,选中和未被选中的外观样式是不同的。典型的做法是通过切换不同的CSS样式名称来转换外观。比如未被选中适合的CSS样式名称可能是MyRadioButton,被选中之后则变成 MyRadioButtonChecked。Dijiti提供了dijit._CssStateMixin混入类来抽象这种行为。

  开发人员的组件只需要继承此类,并通过属性this.baseClass 设置基础的CSS样式名称,就具备根据状态的变化动态修改CSS样式名称的能力。比如设置了baseClass为myWidget,当鼠标移动到该组件上的时候,其根元素的CSS样式名称会自动变成myWidgetHover。该类所支持的状态变化包括鼠标进入/离开、焦点获取/失去、选中/未选中、启用 /禁用等。

时间: 2024-07-30 22:47:15

使用Dijit实现界面组“.NET研究”件化开发的相关文章

用优秀.NET界面控“.NET研究”件 打造新潮界面效果

一直以来,做.NET共享小软件的界面一般采用IrisSkin这个比较不错的皮肤控件来美化界面效果,方便易用,界面效果也还可以.该控件开发应用比较方便,拖动控件到主界面,然后初始化地方添加一下代码即可: string skinFile = ConfigurationManager.AppSettings["SkinFile"];this.skinEngine1.SkinFile = Path.Combine(Application.StartupPath, skinFile); 主界面初

在ASP.NET 2.0中操作数据之十九:给编辑和新增界面增加验证控件_自学过程

导言 在前面三节的示例中,GridView和DetailsView控件使用的是绑定列和CheckBoxField(绑定GridView和DetailsView时,通过智能标记可以令VS根据数据库自动增加对应的类型).当编辑GridView或者DetailsView中的一行时,非只读属性的绑定列将自动转为textbox,以便用户修改现有的数据.同样地,当在DetailsView控件中新增记录时,InsertVisible属性为true(默认值)的绑定列会呈现出空的textbox,以接受用户输入.C

mfc 界面 控件-mfc的界面设计和控件使用问题

问题描述 mfc的界面设计和控件使用问题 现在有多个指标,并且每个指标的评分规则都有多行.如果全部显示在一个界面上会很拥挤,如何实现当我点击一个图标时,会出现一个下拉框,显示相应指标的全部评分规则?求各位高手指点! 解决方案 这需要自定义控件,在MFC中可以参考Subclassing子类化技术,其实就是拦截事件消息,自己响应,而不是采用系统的默认行为.你可以在控件之中包含下拉框数据结构,然后重写单击事件,控制下拉框的显示/隐藏.www.codeproject.com网站创始人写了个开源的Ulti

网站制作流程及界面交互设计研究探讨

交互|设计 很多朋友希望,我能把我做网站的一些流程及经验跟大家分享一下,最近刚好做一次内部培训,所以稍微整理了一下,这些只是针对网页初学者,具有一定平面设计水平的人,对HTML不是很了解,他们可能只是想做一个个人主页而已,所以整体还是趋向于传统的表格布局,这里有很多都是一些我个人刚开学时自己摸索的经验,所以可能不是很专业,但是绝对是比较容易入门的,我一直有这种思想,你只有塌进来了,你才可能往更高的地方爬,我想当初如果没有这段的学习,现在我也不会明白什么W3C,什么CSS,什么ASP,什么XML,

android中响应Fragment界面中的控件的问题

问题描述 android中响应Fragment界面中的控件的问题 Fragment界面中 怎么对其中的控件比如按钮添加监听事件?先说好,在onCreateView()跟onActivityCreated()中添加是没有反应的 解决方案 在 fragment中:(点击button弹出toast)@Override public View onCreateView(LayoutInflater inflater ViewGroup container Bundle savedInstanceStat

设计-Android studio 在XML布局文件中编辑好代码,为什么Design界面创建的控件会重叠?

问题描述 Android studio 在XML布局文件中编辑好代码,为什么Design界面创建的控件会重叠? 新手表示每次都要在Design界面一个一个拖来调整位置,但看教程上并不需要拖.求各位指点~ 解决方案 应该 是因为你在xml并没有排列好控件的布局,重叠很有可能是你把控件都放在了relativelayout里,relativelayout需要手动设置控件的位置 解决方案二: 尽量不要采取拖动方式,使用代码控制会比较好 解决方案三: 默认是相对布局 相对布局的控件式会重叠的

用Winform开发了一个程序,界面上的控件在Win7下是基本对齐的,到了WindowsServer2008下就变的完全对不齐了?请问这是什么原因?

问题描述 用Winform开发了一个程序,界面上的控件在Win7下是基本对齐的,到了WindowsServer2008下就变的完全对不齐了?请问这是什么原因?RT 解决方案 解决方案二:不知道你是用什么方法"对齐"的,所以无法判断.比如说你用"空格"来搞什么"对齐",那么不同系统的同一个主题下的细节设置也是有调整的,空格在高版本的windows下肯定就变宽了一些,那么自然在高版本windows下就"鼓出去"了.你用于"

link 环境下如何让当前界面上的控件全部归零,包括选择框都恢复原来的状态?

问题描述 link 环境下如何让当前界面上的控件全部归零,包括选择框都恢复原来的状态? link 环境下如何让当前界面上的控件全部归零,包括选择框都恢复原来的状态? 解决方案 你可以将构造函数中初始化的代码抽取出来,放在一个独立的方法调用.

c#-界面不显示控件,不显示控件

问题描述 界面不显示控件,不显示控件 如图所示, 解决方案 重启计算机看看,如果你没有添加特殊的代码,可能是你的gfi资源饱和造成的,检查下计算机上有没有不良的软件.尽量关闭.另外禁用aero glass看看. 解决方案二: 是你背景透明化全部透明了?具体代码呢 解决方案三: 是背景被你全给透明了吧.