MVC Architecture(架构)
警告
重要提示:Chrome 将在所有平台上取消对 Chrome 应用程序的支持。 Chrome 浏览器和 Chrome 网上应用店将继续支持扩展。阅读公告并了解有关迁移应用程序的更多信息。
随着现代浏览器功能越来越强大,功能越来越丰富,用 JavaScript 构建成熟的 Web 应用程序不仅可行,而且越来越流行。根据 HTTP Archive 的趋势(trends),部署的 JavaScript 代码大小在一年中增长了 45%。
随着 JavaScript 的流行度攀升,我们的客户端应用程序比以前复杂得多。应用程序开发需要多个开发人员的协作。在新的 Web 应用程序时代,编写可维护和可重用的代码至关重要。 Chrome 应用程序具有丰富的客户端功能,也不例外。
设计模式对于编写可维护和可重用的代码很重要。模式是一种可重用的解决方案,可以应用于软件设计中常见的问题——在我们的例子中——编写 Chrome 应用程序。我们建议开发者按照 MVC 模式将应用解耦为一系列独立的组件。
在过去的几年里,开发了一系列 JavaScript MVC 框架,例如backbone.js, ember.js, AngularJS, Sencha, Kendo UI, 甚至 更多。虽然它们都有其独特的优势,但它们中的每一个都遵循某种形式的 MVC 模式,其目标是鼓励开发人员编写更结构化的 JavaScript 代码。
# MVC pattern overview(MVC 模式概述)
MVC 提供了优于标准 JavaScript 的架构优势——它可以帮助您编写更有条理、因此更易于维护的代码。这种模式已在多种语言和几代程序员中使用和广泛测试。
MVC由三个组件组成:
# Model
模型是存储应用程序数据对象的地方。该模型对视图和控制器一无所知。当模型发生变化时,它通常会通知其观察者发生了变化。
为了进一步理解这一点,让我们使用 Todo list 应用程序,这是一个简单的单页 Web 应用程序,可以跟踪您的任务列表。
此处的模型表示与每个待办事项相关联的属性,例如描述和状态。当一个新的待办事项被创建时,它被存储在模型的一个实例中。
# View
视图是呈现给用户的内容以及用户与应用程序交互的方式。该视图由 HTML、CSS、JavaScript 和通常的模板组成。 Chrome 应用程序的这部分可以访问 DOM。
例如,在上面的待办事项列表 Web 应用程序中,您可以创建一个视图,将待办事项列表很好地呈现给您的用户。用户还可以通过某种输入格式输入一个新的待办事项;但是,视图不知道如何更新模型,因为这是控制器的工作。
# Controller
控制器是决策者,是模型和视图之间的粘合剂。当模型改变时控制器更新视图。它还向视图添加事件侦听器,并在用户操作视图时更新模型。
在待办事项列表 Web 应用程序中,当用户检查项目已完成时,单击将转发到控制器。控制器修改模型以将项目标记为已完成。如果数据需要持久化,它还会异步保存到服务器。在诸如 Chrome 应用程序之类的富客户端 Web 应用程序开发中,将数据保持在本地存储中也很重要。在这种情况下,控制器还负责将数据保存到客户端存储,例如 FileSystem API。
MVC 设计模式有一些变体,例如 MVP(Model-View-Presenter)和 MVVP(Model-View-ViewModel)。即使使用所谓的 MVC 设计模式本身,传统 MVC 模式与各种编程语言的现代解释之间也存在一些差异。例如,一些基于 MVC 的框架会让视图观察模型中的变化,而其他框架会让控制器处理视图更新。本文的重点不是各种实现的比较,而是关注点分离及其在编写现代 Web 应用程序中的重要性。
如果您有兴趣了解更多,我们推荐 Addy Osmani's 的在线书籍:Learning JavaScript Design Patterns。
总而言之,MVC 模式为应用程序开发人员带来了模块化,它支持:
- 可重用和可扩展的代码。
- 视图逻辑与业务逻辑的分离。
- 允许负责不同组件(例如 UI 层和核心逻辑)的开发人员之间同时工作。
- 更容易维护。
# MVC persistence patterns(MVC 持久化模式)
使用 MVC 框架实现持久性的方法有很多种,每种方法都有不同的权衡。在编写 Chrome 应用程序时,请选择您觉得自然并适合您的应用程序需求的具有 MVC 和持久性模式的框架。
# Model does its own persistence - ActiveRecord pattern(模型做自己的持久化 - ActiveRecord 模式)
在 Ruby on Rails 等服务器端框架和 Backbone.js 和 ember.js 等客户端框架中都很流行,ActiveRecord 模式将持久化的责任放在模型本身上,通常通过 JSON API 实现。
与让模型处理持久性略有不同的做法是引入存储和适配器 API 的单独概念。存储、模型和适配器(在某些框架中称为代理)相互配合。Store 是保存已加载模型的存储库,它还提供创建、查询和过滤其中包含的模型实例等功能。
适配器或代理接收来自存储的请求并将它们转换为适当的操作以针对持久数据层(例如 JSON API)采取。这在现代 Web 应用程序设计中很有趣,因为您经常与多个持久数据层交互,例如远程服务器和浏览器的本地存储。Chrome Apps 为客户端存储提供了 Chrome Storage API 和 HTML 5 fileSystem API。
优点:
- 易于使用和理解。
缺点:
- 难以测试,因为持久层被“烘焙”到对象层次结构中。
- 让不同的对象使用不同的持久存储是很困难的(例如,文件系统 API 与 indexedDB 与服务器端)。
- 在其他应用程序中重用 Model 可能会产生冲突,例如在两个不同的视图之间共享一个 Customer 类,每个视图都希望保存到不同的位置。
# Controller does persistence(控制器做持久化)
在这种模式中,控制器持有对模型和数据存储的引用,并负责保持模型的持久性。控制器响应加载、保存、删除等生命周期事件,并向数据存储发出命令以获取或更新模型。
优点:
- 更容易测试,控制器可以通过一个模拟数据存储来编写测试。
- 只需构造具有不同数据存储的控制器,就可以将同一模型与多个数据存储重用。
缺点:
- 代码维护起来可能更复杂。
# AppController does persistence(AppController 做持久化)
在某些模式中,有一个监督控制器负责在一个 MVC 和另一个 MVC 之间导航。例如,AppController 决定“返回”按钮将客户端从编辑屏幕(包含 MVC 小部件/格式)移动到设置屏幕。
在 AppController 模式中,AppController 通过向数据存储发出调用以加载所需的任何模型并为该屏幕构建所有匹配的视图和控制器,从而响应事件并更改应用程序的当前屏幕。
优点:
- 将持久层移到堆栈的更高位置,以便轻松更改。
- 不会像 DatePickerController 这样需要了解持久性的低级控制器造成污染。
缺点:
- 应用程序的每个“页面/屏幕”现在都需要编写或更新大量样板:模型、视图、控制器、AppController。
# Recommended MVC frameworks(推荐的MVC框架)
MVC 对于设计 Chrome 应用程序至关重要。我们推荐使用以下符合 CSP–Compliant 的 MVC 框架来编写安全且可扩展的 Chrome 应用程序:
- AngularJS (Text Drive Reference App and Build Apps with AngularJS tutorial)
- Kendo UI (Photo Booth Reference App)
- Sencha (Video Player Reference App and Build Apps with Sencha Ext JS tutorial)
# Useful resources(有用的资源)
# Online
- HTML5Rocks.com
- Learning JavaScript Design Patterns (by Addy Osmani)
- TodoMVC
# Books
- JavaScript Web Applications (By Alex MacCaw)
- JavaScript Patterns (By Stoyan Stefonov)
- Maintainable JavaScript (By Nicolas Z. Zakas)
By.一粒技术服务