使用这些新小部件增强您的移动应用程序
Dojo Mobile (dojox.mobile
) 是一个 Dojo Toolkit 包,用于创建轻量级移动 Web 应用程序。Dojo 1.8(于 2012 年 8 月发布)包含许多新的 Dojo Mobile 小部件、小部件增强和其他新功能。本文是由三部分组成的系列文章的第一部分,通过许多代码示例探索了这些新功能。在第 1 部分中,将了解 Dojo Mobile 1.8 中引入的新小部件、与小部件相关的实用程序类,以及一些模块。
查看本系列更多内容 0 评论:
2013 年 7 月 30 日
内容
本系列将介绍 Dojo Mobile 1.8 中新增的功能性特性。要充分掌握本系列,您应该熟悉 Dojo Toolkit 和它的 AMD(Asynchronous Module Definition,异步模块定义)支持。
本系列不会介绍 1.8 版中未包含的新增 Dojo Mobile 特性。本系列也不会介绍非功能性增强,比如新的设备和操作系统版本支持;对性能、可访问性、可测试性和适用性的改进,以及主题更新。有关所有 Dojo Mobile 特性的详细信息,请参阅本文后面的 参考资料。
Dojo Mobile 1.8 引入了许多可用于移动应用程序的新的小部件和模块。您可在 dijit
或dojox
包中找到适用于移动应用程序的小部件,但 Dojo Mobile 小部件的设计仅包含有限的特性,以保持其资源占用尽可能小 ― 而且它们提供了特定于移动的主题。
本文将介绍 Dojo Mobile 1.8 中的新小部件、与小部件相关的实用程序类,以及一些模块,还将展示如何使用它们。第 2 部分 介绍对现有特性的新增强,第 3 部分 介绍如何使用 Dojo Mobile 数据处理函数来自定义外部内容视图。
Accordion 是一个容器小部件,可以一种堆栈式格式显示一组子窗格。
立即免费下载 IBM Worklight Developer Edition 5.0,该版本永不过期!使用 Worklight 移动应用程序平台开发和测试您使用 Dojo Mobile 构建的应用程序。
通常,dojox.mobile.Pane
、dojox.mobile.Container
或dojox.mobile.ContentPane
用作子小部件,而 Accordion 不需要特定的子小部件。Accordion 支持 3 种打开子窗格的模式:多选、固定高度和单选。Accordion 可拥有圆角,而且它可延迟加载内容模块。图 1 显示了 Accordion 小部件的实际应用:
在默认情况下,Accordion 中的多个窗格可同时打开。清单 1 在多选模式下实例化 Accordion:
<div data-dojo-type="dojox.mobile.Accordion"> ... </div>
在多选模式下,打开子窗格时,Accordion 业会相应地增高,如 图 2 所示:
如果指定 fixedHeight:true
,如 清单 2 中所示,无论打开哪个窗格,Accordion 的高度都会保持相同:
<div data-dojo-type="dojox.mobile.Accordion" data-dojo-props='fixedHeight:true' style="height:300px;"> ... </div>
图 3 显示了固定高度模式下的 Accordion:
如果指定 singleOpen:true
,如 清单 3 中所示,那么一次只能打开一个窗格:
<div data-dojo-type="dojox.mobile.Accordion" data-dojo-props='singleOpen:true'> ... </div>
在单选模式下,Accordion 的高度依据打开的窗格的高度而变化,如 图 4 中所示:
如果指定 roundRect:true
,如 清单 4 中所示,那么 Accordion 会显示为圆角形式:
<div data-dojo-type="dojox.mobile.Accordion" data-dojo-props='roundRect:true'> ... </div>
图 5 显示了一个圆角的 Accordion 小部件:
如果在一个子窗格小部件中指定 lazy:true
,如 清单 5 中所示,那么仅在第一次打开该窗格时,才会加载其中的所有小部件:
<div data-dojo-type="dojox.mobile.Accordion"> ... <div data-dojo-type="dojox.mobile.Pane" data-dojo-props='label:"Calendar (Lazy)", lazy:true'> <div style="padding:10px"> <div data-dojo-type="dijit.CalendarLite"></div> </div> </div> ... </div>
Accordion 小部件(而不是窗格小部件)会检查 lazy:true
标志并执行延迟加载。
请注意,一个窗格中的小部件模块(和它们所依赖的模块)会自动延迟加载。例如,对于 清单 5,您无需在应用程序中显式要求dijit.CalendarLite
。
图 6 显示了 清单 5中的代码的结果:
回页首
Audio 是一个围绕 HTML5 <audio>
元素(播放音频)的非常瘦的包装器。对于不支持 <audio>
的桌面浏览器,这个小部件会自动将<audio>
替换为 <embed>
。如果不需要使用 Dojo 小部件,那么可以直接使用 <audio>
,而不使用这个小部件。
清单 6 显示了使用 Audio 小部件的示例代码:
<audio data-dojo-type="dojox.mobile.Audio" controls> <source src="sample.mp3" type="audio/mpeg"> <source src="sample.ogg" type="audio/ogg"> <source src="sample.wav" type="audio/wav"> <p>Cannot play on this browser.</p> </audio>
图 7 显示了 Audio 小部件:
回页首
Video 是一个围绕 HTML5 <video>
元素(播放视频)的非常瘦的包装器。对于不支持 <video>
的桌面浏览器,这个小部件会自动将<video>
替换为 <embed>
。如果不需要使用 Dojo 小部件,那么可以直接使用 <video>
,而不使用这个小部件。
清单 7 显示了使用 Video 小部件的示例代码:
<video data-dojo-type="dojox.mobile.Video" controls> <source src="sample.mp4" type="video/mp4"> <source src="sample.ogv" type="video/ogg"> <source src="sample.webm" type="video/webm"> <p>Cannot play on this browser.</p> </video>
图 8 显示了一个在 Video 小部件中播放视频内容(已暂停)的示例:
回页首
Badge 不是一个继承了 dijit._WidgetBase
的小部件,而是一个创建和更新了 Badge 节点的简单的实用程序类。一个 Badge(如 图 9 中所示)包含一个简单的 DOM 按钮:
Badge 可从其他小部件使用,比如 IconItem 或 TabBarButton。
回页首
类似于 Badge,Icon 不是一个继承了 dijit._WidgetBase
的小部件,而是一个简单的实用程序类(在本例中用于创建图标),比如 图 10 中所示的图标:
清单 8 中的代码示例封装了一个图像图标、一个 CSS sprite 图标和一个 DOM 图标的创建:
Image icon: <div data-dojo-type="dojox.mobile.Icon" data-dojo-props='icon:"tab-icon-12h.png"'></div> CSS sprite icon: <div data-dojo-type="dojox.mobile.Icon" data-dojo-props='icon:"tab-icons.png",iconPos:"29,116,29,29"'></div> DOM Button: <div data-dojo-type="dojox.mobile.Icon" data-dojo-props='icon:"mblDomButtonBlueCircleArrow"'></div>
回页首
Carousel 小部件显示了一个内容(通常为图像)列表,可以让用户从中进行快速选择。图 11 显示了 Carousel 小部件的实际应用:
在 Dojo Mobile 1.7 中,Carousel 是一个试验性小部件。在 1.8 中,它经过了重构,被拆分为 DataCarousel(支持旧的 dojo.data
数据存储)和 StoreCarousel(支持新的 dojo.store
数据存储)。图 12 中的类分层结构图演示了这种新结构:
典型的方法是使用 DataCarousel 或 StoreCarousel,通过一个数据存储提供数据,如 清单 9 中所示:
<div data-dojo-type="dojox.mobile.StoreCarousel" data-dojo-props='store:store1, title:"Category"'></div>
公共基类 Carousel
没有数据存储支持。直接使用 Carousel 小部件可能不切实际,但如果按照 清单 10 中所示来排列 Carousel 的子小部件,就可以直接使用 Carousel 小部件:
<div data-dojo-type="dojox.mobile.Carousel"> <div data-dojo-type="dojox.mobile.SwapView"> <div data-dojo-type="dojox.mobile.CarouselItem" data-dojo-props='src:"images/dish1.jpg"'></div> <div data-dojo-type="dojox.mobile.CarouselItem" data-dojo-props='src:"images/dish2.jpg"'></div> </div> <div data-dojo-type="dojox.mobile.SwapView"> <div data-dojo-type="dojox.mobile.CarouselItem" data-dojo-props='src:"images/dish3.jpg"'></div> <div data-dojo-type="dojox.mobile.CarouselItem" data-dojo-props='src:"images/dish4.jpg"'></div> </div> </div>
如果使用 DataCarousel 或 StoreCarousel,则会自动生成 SwapView 和 CarouselItem 子小部件。
回页首
Pane 和 Container 是简单的 <div>
-包装器窗格小部件。Container 继承了 dijit._Container
,而 Pan 没有,如 图 13 中的类分层结构中所示:
不同于 View,Pane 和 Container 没有特殊功能。它们可用于任何用途,比如用作 Accordion、FixedSplitter、GridLayout 等的窗格,或者用于创建一个视图中的一个部分区域。
回页首
EdgeToEdgeDataList 和 RoundRectDataList(它们是支持 dojo.data
的列表小部件)从 Dojo Mobile 1.7 开始已经可供使用。EdgeToEdgeStoreList 和 RoundRectStoreList(1.8 中新增)支持新的 dojo.store
数据存储。用法基本相同,但 dojo.data
与dojo.store
的查询参数不同。
图 14 显示了 EdgeToEdgeStoreList 小部件的一个示例:
回页首
GridLayout 是一个容器小部件,其子小部件放在一个网格布局中,如 图 15 中所示。每个子小部件必须是一个容器小部件,比如dojox.mobile.Pane
。
清单 11 显示了一个使用 GridLayout 小部件的示例:
<div data-dojo-type="dojox.mobile.GridLayout" data-dojo-props='cols:2'> <div data-dojo-type="dojox.mobile.Pane">...</div> <div data-dojo-type="dojox.mobile.Pane">...</div> <div data-dojo-type="dojox.mobile.Pane">...</div> <div data-dojo-type="dojox.mobile.Pane">...</div> <div data-dojo-type="dojox.mobile.Pane">...</div> <div data-dojo-type="dojox.mobile.Pane">...</div> </div>
请注意,每个子小部件的根节点必须是一个 <div>
元素。如果希望放置一些根节点不是 <div>
的内容,则必须将它们封装在另一个根节点是<div>
的小部件中。
可使用 cols
属性指定每行中的列出,如 图 16 中所示:
cols
属性的 GridLayout如果不指定列数(等效于 cols:0
),GridLayout 会为每行包装尽可能多的子小部件列,只要 GridLayout 的宽度容纳得下。
回页首
IconMenu(如 图 17 中所示)是一个弹出菜单:
每个菜单项必须是 dojox.mobile.IconMenuItem
。IconMenuItem 和 ListItem 继承了同一个基类 dojox.mobile._ItemBase
。因此拥有用于执行视图过渡的属性,比如 moveTo
。清单 12 显示了一个使用 IconMenu 小部件的示例:
<ul data-dojo-type="dojox.mobile.IconMenu" data-dojo-props='cols:3'> <li data-dojo-type="dojox.mobile.IconMenuItem" data-dojo-props='label:"Tour", icon:"images/tab-icon-19w.png", moveTo:"view2", transition:"slide", closeOnAction:true'></li> ... </ul>
回页首
ProgressBar 小部件将会显示任务的进度。它显示的值可以是数字(0 到最大值)或百分比(0% 到 100%)。图 18 显示了一些示例:
清单 13 显示了一个使用 ProgressBar 小部件的示例:
<div data-dojo-type="dojox.mobile.ProgressBar" data-dojo-props='maximum:200, onChange:onChange' style="width:275px"></div>
回页首
Rating 小部件显示一个等级,通常用星星表示。图 19 显示了一些示例:
清单 14 显示了一个使用 Rating 小部件的示例:
<span data-dojo-type="dojox.mobile.Rating" data-dojo-props='image:"star-orange.png",numStars:3,value:1.5'></span>
您可以创建和指定自己的 Rating 图像。如 图 20 中的示例所示,它必须包含 3 个等宽的星星(或等效图标),从左到右依次为全星、空星和半星:
回页首
ScreenSizeAware 是一个实验性模块,可帮助您创建能依据屏幕大小而转换 UI 布局的应用程序。在一个电话大小的屏幕上,该应用程序会显示一个填满屏幕的列表小部件。用户可通过选择一个列表项进入另一个视图,如 图 21 中所示:
在一个平板大小的屏幕上,该应用程序显示一个水平拆分视图,它的左侧窗格是一个列表小部件,如 图 22 中所示:
ScreenSizeAware 假设该应用程序由两个水平拆分窗格组成,而且左侧窗格有一个列表小部件,如 清单 15 中的示例中所示:
<div data-dojo-type="dojox.mobile.FixedSplitter" data-dojo-props='orientation:"H"'> <div data-dojo-type="dojox.mobile.Container" style="width:300px;"> <div id="leftView" data-dojo-type="dojox.mobile.ScrollableView"> <h1 data-dojo-type="dojox.mobile.Heading" data-dojo-props='fixed:"top"'>Left Pane</h1> <ul data-dojo-type="dojox.mobile.EdgeToEdgeList" data-dojo-props='stateful:true'> <li data-dojo-type="dojox.mobile.ListItem" data-dojo-props='label:"View1", moveTo:"view1"'></li> .... </ul> </div> </div> <div data-dojo-type="dojox.mobile.Container"> <div id="view1" data-dojo-type="dojox.mobile.ScrollableView"> <h1 data-dojo-type="dojox.mobile.Heading" data-dojo-props='fixed:"top", back:"Home", moveTo:"leftView"'>Right Pane</h1> .... </div> </div> </div>
要使您的应用程序能够感知屏幕大小,您需要要求 ScreenSizeAware 并在应用程序中的某处放入一个 <span data-dojo-type="dojox.mobile.ScreenSizeAware"></span>
标记。然后 ScreenSizeAware 小部件依据当前屏幕大小而转换 UI 布局。应用程序的 HTML 文件中不需要内联 JavaScript 代码。
还有一种替代方法可以将 ScreenSizeAware 应用到应用程序中,无需包含 <span>
标记,您可以使用 FixedSplitter 的 screenSizeAware
属性,如 清单 16 中所示。在本例中,您无需显式要求 ScreenSizeAware,因为它由 FixedSplitter 动态加载。
ScreenSizeAware
属性的用法<div data-dojo-type="dojox.mobile.FixedSplitter" data-dojo-props='orientation:"H", screenSizeAware:true'>
请注意,ScreenSizeAware 模块仍然是试验性的,它的 API 随时可能改变。
回页首
ScrollablePane 是一个拥有触摸滚动功能的窗格。不同于 ScrollableView,它不是一个视图,所以可将它放在一个视图中来创建一个部分滚动区域。在基于 WebKit 的浏览器上,如果 roundCornerMask
属性为 true
,这个小部件将具有圆角,如 图 23 中所示:
清单 17 显示了一个使用 ScrollablePane 小部件的示例:
<div data-dojo-type="dojox.mobile.ScrollablePane" data-dojo-props='height:"200px",roundCornerMask:true'> <ul data-dojo-type="dojox.mobile.RoundRectList"> ... <div>
回页首
SearchBox 是一个新的表单小部件。它是 INPUT type="search"
的一个未模板化的基类。图 24 显示了一个空的 SearchBox 和一个已输入了搜索文本的 SearchBox:
清单 18 显示了一个使用 SearchBox 小部件的示例:
<input data-dojo-type="dojox.mobile.SearchBox" type="search" placeHolder="Search">
回页首
SimpleDialog 是一个用于移动应用程序的对话框。与 dijit.Dialog
相比,它的代码大小要小得多,而且功能更受限制。图 25 显示了 3 个 SimpleDialog 示例:
创建 SimpleDialog 时,它最初是隐藏的 (display="none"
)。要显示它,必须获取该小部件的引用并调用 show()
方法,如 清单 19 中所示:
<script type="text/javascript"> require([ "dijit/registry", "dojox/mobile/parser", "dojox/mobile", "dojox/mobile/compat", "dojox/mobile/SimpleDialog", "dojox/mobile/Button" ], function(registry){ show = function(dlg){ registry.byId(dlg).show(); } hide = function(dlg){ registry.byId(dlg).hide(); } }); </script> </head> <body style="visibility:hidden;"> <div id="dlg1" data-dojo-type="dojox.mobile.SimpleDialog"> <div class="mblSimpleDialogTitle">Rain Alert</div> <div class="mblSimpleDialogText">Do you have an umbrella?</div> <button data-dojo-type="dojox.mobile.Button" onclick="hide('dlg1')">No</button> <button data-dojo-type="dojox.mobile.Button" onclick="hide('dlg1')">Yes</button> </div> <div id="view" data-dojo-type="dojox.mobile.View"> <button onclick="show('dlg1')">Show Dialog</button> </div> </body> </html>
在 清单 19 中可以看到,可以将任意 HTML、文本或小部件直接放入 SimpleDialog 中。
使用这个小部件的另一种有趣方式是加载外部对话框内容,比如 清单 20 中的示例内容:
<div class="mblSimpleDialogTitle">Rain Alert</div> <div class="mblSimpleDialogText">Do you have an umbrella?</div> <button data-dojo-type="dojox.mobile.Button" onclick="hide('dlg1')">No</button> <button data-dojo-type="dojox.mobile.Button" onclick="hide('dlg1')">Yes</button>
使用 _ContentPaneMixin
加载对话框内容,如 清单 21 中所示:
<div id="dlg1" data-dojo-type="dojox.mobile.SimpleDialog" data-dojo-mixins="dojox.mobile._ContentPaneMixin" data-dojo-props='href:"dialog-data.html"'></div>
清单 21 中的示例使用 data-dojo-mixins
属性,动态地将 dojox.mobile.ContentPane
的功能添加到 SimpleDialog 中,这也是 Dojo 1.8 中的一个新特性。
回页首
TreeView 是一个具有树式导航的可滚动视图。这个小部件可连接到一个 dojox.data.FileStore
,充当一个快速的目录浏览器,如 图 26 中所示:
代码 清单 22 实现了 图 26 中所示的 TreeView 视图:
<script type="text/javascript"> require([ "dojox/data/FileStore", "dijit/tree/ForestStoreModel", "dojox/mobile/parser", "dojox/mobile", "dojox/mobile/compat", "dojox/mobile/TreeView" ], function(FileStore, ForestStoreModel){ var store = new FileStore({ url: "dojox/data/demos/stores/filestore_dojotree.php", id: "theStore", label: "name", pathAsQueryParam: true }); treeModel = new ForestStoreModel({ store: store, rootLabel: "Files", childrenAttrs: ["children"], newItemIdAttr: "path" }); }); </script> </head> <body style="visibility:hidden;"> <div data-dojo-type="dojox.mobile.TreeView" data-dojo-props='model: treeModel'></div> </body> </html>
回页首
类似于 SpinWheel,ValuePicker 是一个选择值的小部件。它的 UI 不同于 SpinWheel,但 API 是相同的。图 27 显示了一个示例:
要选择一个值,用户可以单击加号或减号,或者直接在输入字段中输入一个值。这种类型的值选择器通常可在 Android 设备上看到。
清单 23 中的代码实现了 ValuePicker,如 图 27 中所示:
<div data-dojo-type="dojox.mobile.ValuePicker"> <div data-dojo-type="dojox.mobile.ValuePickerSlot" data-dojo-props="labels:['A','B','C','D',...,'Z']" style="text-align:center;width:40px;"></div> <div data-dojo-type="dojox.mobile.ValuePickerSlot" data-dojo-props='labelFrom:3000, labelTo:3100' style="width:70px;"></div> <div data-dojo-type="dojox.mobile.ValuePickerSlot" data-dojo-props='labelFrom:0, labelTo:9' style="width:50px;"></div> <div data-dojo-type="dojox.mobile.ValuePickerSlot" data-dojo-props="labels:['pt','px','cm']" style="width:50px;"></div> </div>
回页首
ValuePickerDatePicker(如 图 28 中所示)是一个基于 ValuePicker 的日期选取器小部件:
使用以下代码在一个标记中实例化这个小部件:
<div data-dojo-type="dojox.mobile.ValuePickerDatePicker"></div>
回页首
ValuePickerTimePicker(如 图 29 中所示)是一个基于 ValuePicker 的时间选取器小部件:
使用以下代码在一个标记中实例化这个小部件:
<div data-dojo-type="dojox.mobile.ValuePickerTimePicker"></div>
回页首
DataPicker 是一个围绕 SpinWheelDatePicker 或 ValuePickerDatePicker 的包装器小部件。TimePicker 是一个围绕 SpinWheelTimePicker 或 ValuePickerTimePicker 的包装器小部件。应该将它们用于自动主题加载器 deviceTheme。如果当前使用的是 android
主题,那么它们会实例化一个基于 ValuePicker 的选取器;否则会实例化一个基于 SpinWheel 的选取器。
图 30 显示了 DatePicker 小部件:
图 31 显示了 TimePicker 小部件:
回页首
migrationAssist 模块可帮助您将 Dojo Mobile 1.6/1.7 应用程序迁移到 1.8 版。要启用 migrationAssist,只需启用这个模块即可,如 清单 24 中所示:
// old API case <script> dojo.require("dojox.mobile.migrationAssist"); dojo.require("dojox.mobile"); .... </script> // AMD case <script> require([ "dojox/mobile/migrationAssist", "dojox/mobile", .... ]); </script>
如果应用程序使用了已不推荐使用或不再可用的功能,这个模块会检测它们并在浏览器控制台中显示相关消息。另外,它会尝试在可能的范围内动态地修复它们,以便目标应用程序能够正常运行。但是,请注意,migrationAssist 的用途不是运行按原样运行旧应用程序,而是帮助迁移。
回页首
pageTurningUtils 是一个试验性实用程序模块,提供了非常类似于真实的书本翻页的翻页效果。 它使您能够创建电子书阅读器或幻灯片放映应用程序中的翻页动画。页面内容可以是任意的 HTML、文本、图像或小部件。图 32 显示了在单页模式下使用的一个 pageTurningUtils 示例:
图 33 显示了一个在双页模式下使用的 pageTurningUtils 示例:
清单 25 中的示例代码演示了如何使用 pageTurningUtils:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1, minimum-scale=1,user-scalable=no"/> <meta name="apple-mobile-web-app-capable" content="yes" /> <title>Page Turning</title> <link href="../themes/common/PageTurning.css" rel="stylesheet"> <script src="../../../dojo/dojo.js" data-dojo-config="async: true"></script> <script type="text/javascript"> require([ "dojo/_base/connect", "dojo/dom", "dojo/ready", "dojox/mobile/pageTurningUtils" ], function(connect, dom, ready, pageTurningUtils){ var w = 285; // width of the page var h = 388; // height of the page var turnfrom = "top"; // "top", "bottom" or "left" var page = 1; // 1:single-page, 2:double-page var dogear = 1.0; // dogear width between 0 and 1 var duration = 2.0; // duration of animation in seconds var alwaysDogeared = false; // all the pages are dogeared or not ready(function(){ var utils = new pageTurningUtils(); utils.init(w, h, turnfrom, page, dogear, duration, alwaysDogeared); utils.initCatalog(dom.byId("catalog")); connect.connect(dom.byId("catalog"), "onclick", function(e){ if(e.offsetX < w / 2){ // clicked on the left half of the image utils.turnToPrev(); }else{ // clicked on the right half of the image utils.turnToNext(); } }); }); }); </script> <style type="text/css"> img{ width: 100%; height: 100%; } </style> </head> <body> <div id="catalog" style="margin:10px;"> <div id="page1"> <div id="front1"><img alt="" src="images/pic1.jpg"></div> <div id="back1"></div> </div> <div id="page2"> <div id="front2"><img alt="" src="images/pic2.jpg"></div> <div id="back2"><img alt="" src="images/pic3.jpg"></div> </div> <div id="page3"> <div id="front3"><img alt="" src="images/pic4.jpg"></div> <div id="back3"></div> </div> </div> </body> </html>
这个示例监听用户的单击事件。如果单击图像的右半部分,则会打开下一页;如果单击图像的左半部分,则会打开上一页。您可能希望试验更改清单 25 中的各种参数。
pageTurningUtils 可同时用于移动和桌面应用程序。请注意,清单 25 不需要 dojox/mobile
。即使 pageTurningUtils 位于 dojox.mobile
命名空间下,它也对 dojox.mobile
没有任何依赖关系。另请注意,这个模块仍然是试验性的,它的 API 可能会有所改变。
回页首
在本文中,您看到了 Dojo Mobile 1.8 中新增的许多小部件、实用程序类和模块。您可以利用这里的代码示例,开始使用这些新特性构建更加强大、富有吸引力的移动 Web 应用程序。另外,不要忘记,除了本文中介绍的新小部件之外,Dojo Mobile 还拥有丰富的现有小部件(参见 参考资料,获取完整 Dojo Mobile 文档的链接)。一定要查阅 第 2 部分,这部分将探索对现有 Dojo Mobile 特性的新增强。