一起谈.NET技术,使用Dijit实现界面组件化开发

  对于组件化的软件工程设计,很多开发人员都比较熟悉。组件化的设计适合于复杂的软件系统和团队协作开发。把软件系统划分成若干个组件,组件之间通过预先定义好的接口和协议进行通讯和协作,共同完成整个软件系统的职责。团队中的开发人员可以各自负责不同的组件。组件化的思想在桌面应用和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来根据标识符获取组件对象。
  • 调用生命周期方法: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来进行事件绑定。这种方式比先手工查询DOM节点,再通过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-09-15 20:41:22

一起谈.NET技术,使用Dijit实现界面组件化开发的相关文章

使用Dijit实现界面组件化开发

对于组件化的软件工程设计,很多开发人员都比较熟悉.组件化的设计适合于复杂的软件系统和团队协作开发.把软件系统划分成若干个组件,组件之间通过预先定义好的接口和协议进行通讯和协作,共同完成整个软件系统的职责.团队中的开发人员可以各自负责不同的组件.组件化的思想在桌面应用和Web应用后台开发中比较流行,相关的技术和实践都比较成熟. 而在Web应用的前端部分,组件化一直进展得比较缓慢.这其中的原因有很多,最主要的是Web应用的前端在开始的时候比较简单,没有组件化和设计的必要.随着Ajax应用的流行,We

一起谈.NET技术,Visual Studio 2010中敏捷开发流程模板的应用

本文将会为您讲述如何使用TFS 2010 MSF Agile 5.0流程模板为迭代项目而提供的工作簿.首先,让我们看一看Visual Studio 2010 IDE中的Team Explorer插件: 接下来,我们将会进入到SharePoint project portal中,为大家展示Team Explorer是如何模拟它的结构的.我们首先右击名字是Team Project的标题的那个节点,如下图所示: 这会让我们进入到SharePoint project portal中,如下图所示.注意Te

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

对于组件化的软件工程设计,很多开发人员都比较熟悉.组件化的设计适合于复杂的软件系统和团队协作开发.把软件系统划分成若干个组件,组件之间通过预先定义好的接口和协议进行通讯和协作,共同完成整个软件系统的职责.团队中的开发人员可以各自负责不同的组件.组件化的思想在桌面应用和Web应用后台开发中比较流行,相关的技术和实践都比较成熟. 而在Web应用的前端部分,组件化一直进展得比较缓慢.这其中的原因有很多,最主要的是Web应用的前端在开始的时候比较简单,没有组件化和设计的必要.随着Ajax应用的流行,We

《创业家》牛文文:少谈点模式多谈点技术

"模式"如同当年的"主义",流行于各种创业大赛.创业励志节目.论坛的"街头"式秀场 文/创业家 牛文文 "美国某某公司你知道吧?就是刚被戴尔.惠普.思科十几亿美元抢购的那家.我们的模式和它的一样,现在还没赢利,可将来起码有十几亿人民币的市值." "我开了小煤矿,但煤运不出去,上商学院之后受到启发,想搞模式创新,具体讲就是想在铁路边上搞个煤炭物流开发区,建一个大的物流和信息流平台,把分散的煤炭集中在我这个园区,这样和铁

一起谈.NET技术,WPF企业内训全程实录(上)

一. 摘要 圣殿骑士由于工作和项目需要,所以对一些技术进行了较为深入的研究,之前在整个公司做过一些技术专场的培训,由于每次时间较短且人员较多的关系,没能讲得很透彻.一直都想以文字的形式把这些培训细节写出来,但是发现进度确实很慢,所以先来几篇宏观的讲解,希望能起到"授人与鱼也授人以渔"的效果.今天我们就来分享一下WPF内训之旅,这篇文章以WPF培训为主线,中间贯穿了一些其他技术和使用心得.其他培训专题诸如"OO到设计模式"."WCF基础到企业应用"

一起谈.NET技术,梦想创造可能——盘点微软 .NET 技术八年发展历程

文 / 刘如鸿 2000年对于微软是颇有意思的一年,一方面终于迈入了21世纪,担心许久的千年虫问题也没有预想中的那样大面积爆发,通过Windows 95和Windows 98的成功,微软在桌面电脑市场取得了绝对垄断的地位.虽然官司不断,但通过IE捆绑策略也终于彻底打败了傲慢的Netscape,搭上了互联网班车.而Windows 2000的发布也结束了Windows 98和Windows NT两个平台互不兼容.互相掐架的问题,在全新的NT 5.0内核上,服务器和客户端操作系统终于得到了整合.至于办

一起谈.NET技术,你应该知道的15个Silverlight诀窍

我热爱Silverlight,并且身体力行写了很多Silverlight程序,也讨论了很多关于Silverlight的技术.对于刚刚接触Silverlight的开发人员来说,这篇文章是最适合你的.这篇文章列出了我使用Silverlight进行开发后,发现的15条小诀窍.如果你是一个全职的Silverlight开发的话,我希望你能了解并掌握它们. 我不会谈论MVVM,Prism或者MEF这些复杂的以至于吓跑读者的东西. 1. 下图中黄色的高亮文字代表了Silverlight 对象的MIME类型,而

求详细解答-软件漂亮的界面是如何开发的呢?

问题描述 软件漂亮的界面是如何开发的呢? 各位大神请问漂亮的软件界面是如何开发的呢?需要用到什么软件.是不是要用到PS或者Maya啊?但是用哪些软件做出漂亮的模型之后,又是怎样编码实现功能的呢?拜托讲得详细点,因为这个问题困扰我很久了,拜托了大神们!!! 解决方案 对于这个问题,你的Html和Jsp基础一定要是有的,还有就是你需要学会Jquery这种编程语言,等你学会了Jquery时,你会相当嫌弃你的JS技术的,因为Jquery有很多特效,这样做出来的界面会很漂亮的,动态效果很好... 解决方案

Android界面组件的抖动效果实现

 Android实现界面组件的抖动效果采用的Animation动画, 在系统提供的API Demos: 目录为 android-sdksamplesandroid-8ApiDemos 中已经实现了简单的抖动效果 : 具体使用如下: 第一步:准备两个动画效果的XML文件,加入到 res/anim/目录下: Shake.xml文件: <translate xmlns:android="http://schemas.android.com/apk/res/android" androi