`
子衿青青
  • 浏览: 110949 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

使用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代码中以声明式的方式创建,如

对话框标题

对话框内容

声明式的方式在一定程度上简化了开发人员使用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 : "
Hello
" });

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

  • 在HTML模板中直接引用组件中的属性。比如组件中有个属性叫title,在HTML模板中想引用该属性的值,可以直接写${title}。如果属性title的值是"Hello",那么上述模板在运行时刻会变成Hello
  • 通过dojoAttachPoint来声明在组件对象中可见的DOM节点。当需要在组件中引用某个内部的DOM节点时,不需要再次进行查询,通过 dojoAttachPoint即可。如声明
    ,就可以在组件对象中通过 this.myNode来引用该SPAN元素。
  • 通过dojoAttachEvent来进行事件绑定。这种方式比先手工查询DOM节点,再通过dojo.connect来绑定要简单得多。如声明
    Test
    ,就意味着将组件的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。该类所支持的状态变化包括鼠标进入/离开、焦点获取/失去、选中/未选中、启用 /禁用等。

本文已经首发于InfoQ中文站,版权所有,原文为《使用Dijit实现界面组件化开发》,如需转载,请务必附带本声明,谢谢。
InfoQ中文站是一个面向中高端技术人员的在线独立社区,为Java、.NET、Ruby、SOA、敏捷、架构等领域提供及时而有深度的资讯、高端技术大会如QCon 、线下技术交流活动QClub、免费迷你书下载如架构师》等。​

分享到:
评论

相关推荐

    Dojo 小部件开发演示

    通过深入理解和实践Dijit的API,开发者可以构建出符合业务需求的定制化组件,从而简化项目开发,增强应用程序的可维护性和可扩展性。在这个"Dojo小部件开发演示"中,我们看到了Button和FilteringSelect的组合使用,...

    Dojo包下载 包含dijit dojo dojox util四个文件目录

    2. **dijit**: dijit是Dojo的UI组件库,提供了各种预先封装好的可复用界面元素,如按钮、表单、布局容器、对话框等。这些组件具有高度的可定制性,可以适应不同的设计风格,并且符合WAI-ARIA无障碍标准,增强了用户...

    aurora:Dojotoolkit Dijit 的定制主题

    Dojo Toolkit是一个强大的JavaScript库,它提供了丰富的UI组件和工具,而Dijit是Dojo中的一个模块,专注于提供可复用且可主题化的用户界面组件。在这个定制主题的过程中,我们将会探讨如何通过CSS来调整Dijit组件的...

    dojo guide ppt

    它通过Dijit组件系统提供了丰富的用户界面元素,并以模块化和易于使用的特性,促进了高效、现代的Web应用开发。无论你是Ajax新手还是经验丰富的开发者,Dojo都能提供必要的工具和资源,助你在Web开发的道路上...

    dojo开发帮助文档

    Dojo 是一个强大的JavaScript 库,它为Web 开发提供了丰富的功能和工具,包括模块化、用户界面构建、数据管理、动画效果以及AJAX交互等。这个“dojo开发帮助文档”是针对Dojo 1.9版本的详细指南,旨在帮助开发者深入...

    dojo工具包

    2. Dijit:Dijit是一个丰富的用户界面(UI)组件库,提供了各种各样的可复用的、样式化的、无障碍的控件,如按钮、表单、菜单、对话框等。Dijit组件遵循WAI-ARIA标准,确保对残疾用户的友好性。 3. Dojox:Dojox是...

    dojo实现省份地市级联

    Dojo是一个强大的JavaScript工具包,它提供了丰富的UI组件、模块化开发框架和数据管理功能,适用于构建复杂的Web应用。在本案例中,Dojo将被用来创建两个相互关联的下拉列表:一个用于省份,另一个用于地市。 首先...

    dojo基础知识内容简介

    Dojo的窗口系统——dijit,是其核心层面,用于快速开发和重用用户界面组件。dijit利用HTML的扩展属性来声明和配置组件,使得开发人员能够利用熟悉的HTML和CSS创建可复用的客户端组件。例如,通过在HTML元素上添加...

    dojo离线工具

    Dojo是一个广泛使用的开源JavaScript库,它提供了一系列功能强大的工具,包括UI组件、数据管理、动画效果、AJAX交互以及模块化开发等,帮助开发者构建高性能、可维护的Web应用。 Dojo离线工具主要包含以下组件和...

    dojo relase

    它还提供了一个强大的组件化系统,如Dijit UI库,用于构建复杂的Web界面。 3. **Dijit**:Dijit是Dojo的UI组件库,包含了一系列可复用的、符合Web标准的用户界面元素,如按钮、表单控件、对话框、布局容器等。Dijit...

    dstore-and-dijit:与dstore和Dijit同步

    在IT行业中,JavaScript是一...总结来说,dstore和Dijit是JavaScript开发中非常有用的工具,它们帮助开发者高效地管理数据并创建用户友好的界面。通过掌握这两个库的集成使用,可以构建出高度响应、数据同步的Web应用。

    dojo源文件+学习笔记

    Dijit 是Dojo的UI框架,提供了一系列可复用的、响应式的、符合Web标准的用户界面组件,如按钮、表单、对话框、布局容器等。Dijit组件基于WAI-ARIA标准,保证了良好的可访问性。 5. **Dojo Data**: Dojo Data API...

    dojo1.3.1包

    3. **Dijit**:Dijit是Dojo的UI组件库,提供了多种可复用的、样式化的用户界面元素,如按钮、表单、对话框等。在1.3.1中,Dijit的可访问性和国际化支持得到了加强。 4. **Dojo Data**:这是一个数据模型接口,用于...

    Dojo的一些学习资料

    Dojo 是一个强大的JavaScript工具库,它为Web开发提供了丰富的功能和组件,涵盖了从DOM操作、事件处理到AJAX通信,再到复杂的用户界面构建。在深入探讨Dojo的知识点之前,我们先简单了解一下Dojo的核心概念。 1. **...

    技术基础:从头开始学习 Dojo

    3. **Dijit**:Dijit 包是 Dojo 的扩展 UI 库,包含各种用户界面组件,如对话框、日历、调色板、工具提示、树形视图,以及增强的表单控件和布局管理选项。Dijit 提供丰富的交互体验,是构建富互联网应用的关键。 4....

    Pragmatic.Bookshelf.Mastering.Dojo.Jun.2008.pdf

    6. **Dijit UI组件**:Dojo的dijit层提供了丰富的用户界面组件,如按钮、下拉框、对话框、表格等,这些组件都是可定制和可复用的。书中会详细解释如何使用和自定义这些组件。 7. **国际化与本地化**:Dojo支持多...

    dojo组件资料

    7. **dijit**: Dojo的UI组件库,包含了丰富的用户界面元素。 8. **dojo.data**: 数据存储和检索机制,用于与后台数据源交互。 9. **dojo.xhr**: 异步请求(Ajax)功能,用于与服务器通信。 10. **dojo.parser**: ...

    Dojo之Widget标签开发 - 我为人人,人人为我 - BlogJava

    在实际开发中,开发者需要根据具体需求选择合适的Widget类型,如使用`dijit/form/Button`创建按钮,或使用`dijit/layout/BorderContainer`构建复杂的布局。同时,利用Dojo的模块系统和Widget体系,我们可以创建出...

    dojo-release-1.9.2-demos.tar.gz

    《Dojo 框架深度探索:以 dojo-release-1.9.2-demos.tar.gz 为例》 ...通过实际操作这些示例,我们可以更好地掌握Dojo的模块化、组件化、数据绑定和国际化等特性,从而在Web开发项目中更高效地利用Dojo的力量。

Global site tag (gtag.js) - Google Analytics