官网 https://dojo.iohtml
在热衷敏捷交付的时代,鼓励将小功能点持续地交付给用户。软件行业开始青睐这种方式,由于它最大限度地下降风险,并最大限度地提升用户的参与度和满意度。git
即便采用现代的交付方式,一些风险仍然不可避免。复杂性就是这样一种风险,对于成熟的应用程序而言,复杂性更成为一个重要的关注点。不管应用程序遵循什么样的系统架构,随着时间的推移,许多小功能汇集出一个庞大且使人畏惧的代码库,须要几个团队监督。程序员
应用程序上线的时间越久,实现一个设计简洁的新功能的机会就越少。相反,更多的是在现有功能的基础上调整、修复 bug 或扩展。一个成功的应用程序——以及所包含的功能——大部分时间都花在维护上。github
维护复杂的应用程序须要通过严格的训练。团队很容易陷入泥潭,将时间花在抱怨代码和同事上面,而不是向用户交付价值。要下降这种风险涉及不少方面,包括标准化、模式化、技术选型和工具等领域。web
在软件交付的生命周期中,错误发现的越早越好。在开发阶段修复一个错误,比在交付环节修复错误,或者已给用户带来负面影响的上线阶段修复错误要快的多,成本也低得多。typescript
早期捕获错误的好方法是在应用程序的开发阶段支持强类型。若是应用程序的代码中显式指定了类型信息,就能够避免数据类型不匹配而致使的逻辑错误。编译器和静态类型检查程序能够验证类型信息,并当类型不匹配时让构建失败。只有修复了这些错误,软件才能从我的的工做空间进入到交付管道的后续环节。数据库
Dojo 构建在 TypeScript 之上,提供了显式的类型和静态编译时的类型检查。使用 Dojo 构建的应用程序能够用到 TypeScript(而不是普通的 JavaScript)带来的优点。浏览器
当使用 Dojo CLI 构建应用程序时,应用程序的构建过程会默认包含 TypeScript 的编译阶段。开发人员从一开始就能编写出类型安全的应用程序。安全
理想状况下,一个组件应该足够小,以便它只实现单一职责。一个组件越简单、封装程度越高,则大量程序员长期理解和维护时就越容易。拥有庞大代码库的大型应用程序就是由大量的更小、更容易理解的组件组合而成的。性能优化
试图下降复杂度时,在单个组件中隔离职责有如下好处:
对于 web 应用程序而言,隔离还能为终端用户带来额外的好处。应用程序能够划分为多个层,用户在给定的时间点只加载他们感兴趣的层。这减小了资源大小和网络传输需求,从而缩短了加载时间。
HTML 页面是每一个应用程序的基本内容,Dojo 应用程序也不例外。传统上,单个 index.html
文件既是应用程序的入口点,也是将应用程序的总体结构存入 DOM 的根容器。
Dojo 应用程序一般会注入到单个 DOM 元素中,默认状况下是注入到 document.body
中。这使得 Dojo 应用程序能够与页面中的其余内容共存——静态资源、传统的应用程序、甚至是另一个 Dojo 应用程序。
Dojo 中的部件与 DOM 元素相似,是 Dojo 应用程序中封装的核心概念。正如传统网站是经过 DOM 元素逐层构建的同样,Dojo 应用程序则是经过部件逐层构建的。
部件能够描述一切,从单个界面元素(如 label 或 textbox)到更复杂的容器(如 form 表单、页面或者整个应用程序)。
相似地,并不是 DOM 中的全部元素都对用户可见,Dojo 部件不只提供用户界面,也能够实现应用程序的全部幕后需求。
详见建立 Dojo 部件参考文档,了解如何在应用程序中建立部件。
Dojo 部件能够是一个渲染函数工厂或者 TypeScript 类,一般包含在单个 TypeScript 模块中。该模块封装了组成部件的大部份内容,包括它的行为以及虚拟 DOM 的语义化表示。
部件经过属性接口向外部消费者提供 API。这个接口既可包含状态字段列表,在渲染时注入到部件中;也能够包含函数,当事件发生时,部件须要通知应用程序的其余部分时调用,好比部件状态的变动。
部件的外观样式是交由 CSS 设置的,与常规的 HMTL 元素样式相似。CSS 模块用于封装单个部件的样式,避免与其余部件的 CSS 类名冲突。
部件导入 CSS 模块跟导入其余 TypeScript 模块同样,并容许经过对象属性引用 CSS 类名,这些属性会在开发人员的 IDE 中自动提示。在定义部件的语义元素结构时,可使用这些属性名指定样式类。部件中的 CSS 类名和最终的样式类名不一致,而这能够在构建阶段识别出来。
虽然部件的 CSS 模块能够彻底封装自身的样式,但一般也须要一些灵活性。部件能够在应用程序的不一样配置下使用,每一个配置都有本身独特的外观需求。Dojo 提供了覆盖特定样式的能力以知足这个需求。
为了支持应用程序层面外观的一致性,能够经过主题进一步控制部件的样式。
详见 Dojo 样式和主题参考文档,了解如何为单个部件设置样式。
企业应用程序一般须要持久化状态,并容许用户以各类方式查看和操做这些数据。当须要同时在多处访问和编辑同一数据,且要保持数据的一致性时,状态管理能够成为大型应用程序中最复杂的领域之一。
状态一般存在位于 web 应用程序组件外部的数据存储或数据库中,这意味着一些状态管理复杂性须要在应用程序以外解决。然而,对于数据在应用程序与其用户之间流动的状况,有几个范例可以大大的下降管理复杂状态的风险。
以命令式方式编写的应用程序会描述应更改哪些数据,应该如何更改,以及指定必须在什么时候何地更改。若是经过某种形式的计算或赋值在逻辑上链接多块数据,则这些链接在一段时间后只能表示成离散的点。长此以往,除了这些点以外,可能会以违反预期逻辑链接的方式修改任何数据值。
相反,以响应式方式编写的应用程序设法提高数据之间的逻辑链接,并放弃对明确地指定什么时候何地修改数据的控制,以使逻辑数据链接始终保持一致。
具备多个服务层的复杂应用程序可能会在多处描述相同的数据,由于它们散落在应用程序的各处——这方面的一种常见模式是使用数据传输对象。一段数据的描述位置越多,则维护应用程序状态完整性的复杂度呈指数级增加。
任何应用程序只要 UI 须要动态展现(包括 web 应用程序),都会遇到维护逻辑数据链接一致性的问题。这些应用程序中的数据一般至少有两种表示方式。
假设有一个代办事项应用程序,它存储了一组任务,当向用户显示时,每一个任务都有如下两种数据表示方式:
若是用户只能查看任务,则有几个问题与如何修改任务的描述以让用户可见有关。
若是在底层的数据存储中更改了任务,则须要经过 UI 向上传播新的描述信息,这样用户就不会查看过期的数据。若是任务显示在 UI 的多个位置,则全部实例都须要更新,确保用户不会在不一样位置看到的数据不一致。
若是用户还能够修改任务(好比更改描述信息),则还须要解决其余问题。
任务描述如今有两处真正的来源:数据存储中的旧值,以及用户在 textbox 中输入的新值。
而后,须要将修改请求传回给底层的数据存储,以便用新值替换旧值。修改完成后,须要将新的任务描述返回给用户,让用户看到更改后的正确值。尝试修改任务描述时会发生的任何错误也须要在数据交换时考虑。
对于最基本的状态管理需求,部件可使用本地变量管理自身的状态。虽然这种方法有助于隔离和封装,但它只适用于很是简单的用例,如只在应用程序中出现一次的部件,或者与应用程序处理的全部其余状态都断开了链接的部件。
随着在部件间共享状态的需求增长,Dojo 支持响应式的控制反转。将状态提高到父容器部件中,而后使用子部件的 properties 接口注入到子部件中。若是须要,这种状态提高能够横穿整个部件层级,将状态集中在应用程序根部件中,而后将部分状态注入到相关的子分支中。
对于更复杂的需求,或者对于较深的部件层级且不但愿在不相关的中间层传递状态,则外部的数据存储多是最好的方法。集中的数据存储可以帮助应用程序处理大量的状态,容许复杂的状态编辑操做,或者在多处请求相同的状态子集。
Dojo 提供了一个 Store 组件,它支持多种高级的状态管理需求,例如:
Web 应用程序本质上是经过用户界面提供体验的,应用程序的做者须要考虑各类因素,以向用户展现最好的界面。一致的可视化外观和可访问性一般是最显眼的因素,但也须要关注效率和性能,不管是应用程序的逻辑,仍是交付的内容,都有助于提高 web 应用程序的用户体验。
应用程序提供最佳用户体验的一种方式是向最终用户提供一致的外观。这可能与在相似的元素中使用一致的字体同样简单,但一般会扩展到使用相同的色调显示应用程序,甚至实现一整套设计语言,如 Material Design。
Dojo 的样式管道使用 CSS 模块将样式规则封装到特定的部件中,避免在大型代码库中交叉污染。可是,样式并非彻底隔离的——集中的 CSS 变量可以定义公共的主题属性并在应用程序的全部部件间共享。也能够为 Dojo 部件套件提供自定义主题。
详见 Dojo 样式和主题参考文档,了解如何建立应用程序主题。
经过部件套件,Dojo 提供了一些现成的 UI 组件。开发人员能够当即使用这些部件制做许多常见的页面,如 combobox、button、list、tab、text input 和 calendar 等部件。
Dojo 的部件支持国际化、可访问性和主题,让开发人员在无需自定义 UI 组件的状况下,可以灵活的交付应用程序专有的用户体验。
虽然有些应用程序为用户提供了一个主视图,其中能够处理大部分工做,但不少应用程序中用户须要访问更多的区块。帮助页面、设置面板或者分步骤工做流这些例子中,应用程序可能有多个界面,用户能够在任什么时候间访问这些界面。
应用程序的每块内容都须要惟一标识符,这样用户就能够访问它们。这些标识符也必需要支持为连接设置书签和分享连接,以便跳转到应用程序特定区块。用户也须要在不一样区块间导航,以即可以访问应用程序提供的全部功能。导航能够前进到下一步、后退到上一步或者根据用户的选择在多个选项间跳转。
使用静态文件的传统网站包含可单独识别的内容,由于站点中的每一个静态文件都能单独访问。HTML 文件可以使用锚点元素,经过点击连接在不一样文件间导航,而没必要手动修改浏览器地址栏中的 URI。
顾名思义,单页面 web 应用程序只有一个主文件,用户经过该文件访问整个应用程序。可是,这些单页面应用可使用 URI(连同 URI 已有的优势)来标识每个小节。
路由组件为跨层级的路由提供了导航选项,并会将相应的已标识的路由分发到相应的应用程序区块。路由还将处理任何错误条件,例如导航到不存在的路由。
Dojo 的路由系统容许将 URL 的子路径注册为路由,以连接到某个特定类型部件上,这个特定类型的部件称为 Outlet。当用户导航到特定的路由时,将会渲染注册到该路由上的 Outlet 部件。
当用户导航到 Outlet 时,就会“渲染” Outlet,但 Outlet 不多直接处理应用程序的渲染。Outlet 主要是处理导航的封装器(传入查询参数或者处理错误的回调),而将渲染功能委托给应用程序中的其余部件。
相似于在传统 HTML 页面中使用的锚点,应用程序可使用与 Outlet 关联的 Link 部件向用户提供导航选项。
当使用路由时,Dojo 的构建系统能为应用程序中的全部顶级路由自动生成单独的包。而后能够根据须要将每一个包独立的交付给用户。
详见 Dojo 路由参考指南,了解如何在本身的应用程序中实现路由。
动态网站内容(即包含 JavaScript)成为 web 的一部分已经有不少年了。长期以来,站点就能够包含一些脚原本操做 DOM,进行添加、更新或删除内容。可是,Web 的起源(至今仍然是它的一大关键特征)是以静态页面为基础的。随着时间的推移,浏览器的 DOM 实现获得了优化,以便尽量高效地、快速地向最终用户渲染静态内容。
近年来,随着 web 应用程序愈来愈复杂,浏览器已经过 DOM 性能优化作出了回应,针对动态内容做了优化。然而,为了渲染用户界面,web 应用程序仍然须要与一套几十年不变的命令式 API 交互。围绕响应式数据传播而设计的现代 web 应用程序须要一种更高效的方式,将用户界面转换为网页的 DOM。
Dojo 将 DOM 从应用程序中抽象出来,推荐使用响应式状态流来最小化应用程序的样板文件,同时提升了渲染性能。部件会在渲染函数中输出虚拟节点,这些渲染函数使用虚拟 DOM 描述部件的结构层级。而后,框架以尽量高效的方式处理 VDOM 的渲染,只会影响实际须要修改的 DOM 元素。
须要从 DOM 中获取具体信息来实现其需求的应用程序,Dojo 经过中间件系统提供了另外一种 DOM 抽象层。Dojo 中间件以一致的方式解决了这些问题,并仍然支持横跨应用程序的响应式数据流。
随着 web 应用程序规模的增加,当一个任务只须要访问一部分资源时,却必须加载应用程序的全部资源,这样效率就会愈来愈低。每个应用程序资源都有一个与大小相关的成本:内存空间需求和网络上的数据传输;全部这些都会影响到用户开始工做以前须要的等待时间。让应用程序只在须要的时候加载所需的内容,从而将此成本保持在最低水平,这符合用户的最大利益。
获取应用程序的资源时,在 HTTP 资源协商方面会产生额外的开销。客户端须要请求数据,而后客户端必须等待服务器发送完资源的最后一个字节。更严重的状况下,开销还包括 DNS 解析、TCP 链接重建和 TLS 密码/证书协商。
浏览器能够有效地减小这一开销,可是浏览器不能彻底消除这一开销——应用程序也有责任来减小资源传输的开销。与资源的大小相比,获取一个应用程序资源的开销是相对不变的。获取1KB 文件的开销与获取100KB 文件的开销相似。
所以能够经过两种方式下降开销:减小资源总数和增长单个资源的大小。web 应用程序能够经过分层和将相关的资源打包来实现这两种方式。
单个层中应该包含应用程序中特定功能相关的资源集。当用户访问该功能时,层中的全部资源可能同时加载。而后一个层包含的全部内容均可以打包到一个文件中,以便更高效地传送给用户。
当使用 Dojo 的路由系统时,应用程序能够从自动分层和打包中获益。应用程序中的每一个顶级路由都成为一个单独的层,Dojo 的构建系统会自动打包每层内容。这样就能够对层分离,以及打包资源,而不须要配置额外的工具链。这种自动化方案有一处折衷,即在每一个包中都内联和复制了跨多个层的公共依赖项。
复杂的应用程序可能须要对层或包的定义作更细粒度的控制。例如,若是应用程序有一组横跨多个路由的公共依赖项,不要在每一个包中内联或复制这些依赖,则须要将公共依赖提取到本身的包中,而后在第一次引用时延迟加载。
Dojo 的构建管道容许在应用程序的 .dojorc
构建配置文件中指定资源包,而后能自动将横跨多个包的模块依赖项转换为延迟加载的引用。
Web 本质上是全球性的,为其编写的应用程序须要支持全部用户。文本须要按用户选择的语言和脚本显示,而且须要根据用户的区域设置对日期、时间、数字和货币等值进行相应的格式化。
Dojo 容许轻松使用消息包将文本消息从应用程序逻辑中分离出来,而后根据须要选择使用 Unicode CLDR 数据的相关部分支持更高级的值格式化。
开发 web 时,须要应用程序对用户足够包容,不论用户是否须要可访问性。W3C 的可访问性提案已经帮助标准化了许多这方面的需求,包括对可访问的富 Internet 应用程序作的额外工做。
使用 Dojo 的部件套件开发的应用程序已提供了现成的 WAI-ARIA 属性。虽然 Dojo 在这一点上提供了帮助,但它只也只能作这么多——应用程序做者有额外的责任来验证他们的应用程序提供的可访问性级别。建议在应用程序的交付生命周期中包含显式的可访问性测试步骤。
详见 Dojo 国际化参考文档,了解如何为全球用户开发 Dojo 应用程序。
当前社会,Internet 的重要性与日俱增,应用程序被要求能适应用户访问 web 的各类方式。较小尺寸的移动体验已经超过了桌面,但较大的外观仍然能够知足复杂的应用程序需求。Dojo 提供了多种解决方案,帮助开发人员建立适应用户访问需求的应用程序。
当须要预渲染内容时(如开发静态站点时),Dojo 应用程序能够利用构建时渲染(BTR),应用程序结构的一部分或所有都是在构建时计算的,而不是在用户浏览器中运行时计算的。Dojo 提供了一个灵活的基于块 BTR 的解决方案,当构建应用程序时能运行 Node.js 脚本,支持读取文件来获取内容等功能。Dojo 的 BTR 解决方案也支持渐进式融合,以在预渲染内容之上支持动态行为。
渐进式 web 应用程序(PWA)有助于提供与本地设备 App 接近的体验,同时依然能从 web 支持的可移植性和易交付等功能中受益。Dojo 经过简单的构建配置就能帮助建立 PWA,开发人员能够在应用程序中添加离线使用、后台数据同步和推送通知等。
Dojo 容许开发人员经过中间件系统,在全部的交付目标上以一致的方式使用几个即将可用的 web API。Intersection observer API 用于更好的控制渲染,仅渲染用户可见的部件,例如支持无线滚动列表。Resize observer API 可以让应用程序动态响应视窗大小的变化,容许界面在桌面和移动视窗的全部分辨率间逐步适应。
Dojo 为开发 web 应用程序提供了一个端到端的管道。应用程序的做者可使用 dojo create app
CLI 命令快速建立 Dojo 应用程序。而后可使用 dojo build app
命令在开发模式和生产模式下构建应用程序。使用本地 HTTP 服务运行应用程序,并监视对项目文件的修改,构建工具为快速开发和迭代提供支持。使用这种机制,开发人员能够在运行的应用程序中更改代码并能当即看到结果。
这些命令是模块化 Dojo CLI 工具链的一部分,该工具链支持开发生命周期中的各类使用。经过应用程序根目录下的 .dojorc
配置文件,能够配置应用程序的构建管道。
详见 Dojo 构建参考文档,了解如何使用 Dojo 构建各类应用程序。
编译器和静态类型检查程序没法捕获出全部的错误。编写的功能在语法和逻辑上是有效的,但要么在运行时出现没法预见的问题,要么不是按预期的要求执行功能。为了下降这种风险,须要进行额外的测试。
当使用 Dojo CLI 构建应用程序时,默认会内置一个 Intern 测试库的测试运行器。这样开发人员人员在编写应用程序功能的同时就能够当即编写测试代码。
Intern 为不少测试场景提供了解决方案,但可能不足以知足项目的全部测试需求。Dojo 也提供了一个简单的测试工具,容许应用程序测试代码在 VDOM 的抽象层级验证框架和部件。这个工具能够用在不少测试运行器中,如 Intern、Jest 或应用程序测试策略所需的任何其余程序。
详见 Dojo 测试参考文档,了解如何高效测试 Dojo 应用程序。