使用 AngularJS 的单页 Web 应用程序






4.88/5 (6投票s)
本文介绍了单页 Web 应用程序的概念,并详细介绍了如何使用 AngularJS 构建其中的一些。
介绍
在最近一段时间,我们使用任何 Web 技术构建 Web 应用程序,当谈到这些应用程序的客户端编程时,我们大多数人使用纯 OOJS 或 Jquery 来进行一些验证,并在一定程度上使用 XMLHttpObject 或 $.ajax 与服务器通信。许多框架提供了服务器端 MVC 框架,它们在关注点分离、职责模式方面提供了极大的优势,使得代码更易于管理和清晰。
随着 ExtJS、AngularJS 等 JavaScript 世界中一些优秀框架的演进,我们尝试将服务器端的优势带到客户端。
这些框架在构建丰富的客户端应用程序时非常出色。这些框架通过利用异步调用的强大功能,提供了一种非常有趣的构建客户端应用程序的方式。他们称之为“单页应用程序”。
我所说的 SPA,是指客户端只需向服务器请求一次完整的 HTML 页面,那就是您在浏览器中输入 URL 并按 Enter 键的那一刻,服务器会响应一个 HTML 文件,其中包含一些 JavaScript 代码,这些代码会展开客户端的 MV* 应用程序,负责其余所有事情,从导航到服务器调用再到渲染等。
这些框架的优点在于,现在您可以实现完全的关注点分离,我们有模型来处理数据,视图来显示数据,以及一些称为控制器或视图模型的组件来处理操作。
我使用 AngularJS 构建 SPA 已经有一段时间了,我非常喜欢 AngularJS 简化构建此类应用程序的方式,同时也减少了我们为了实现特定功能而必须编写的代码行数。这是选择 AngularJS 作为本文主题的主要原因。
您可以在他们的网站上找到更多关于 AngularJS 的信息。对于初学者,您可以在 egghead 门户网站找到很好的视频。
AngularJS 简介
我将简要介绍一些本文可能使用的术语,以便任何人都可以阅读本文而无需频繁参考其他来源。
AngularJs 是一个由 Google 和社区维护的开源 Web 应用程序框架,旨在帮助开发人员创建单页应用程序。它的目标是增强 Web 应用程序的模型-视图-控制器(MVC)功能,以使开发和测试更容易。
主要设计目标
- 将 DOM 操作与核心逻辑解耦
- 测试驱动开发
- 将客户端和服务器端解耦。这使得开发工作可以并行进行,并且可以重用双方。
- 指导开发人员完成构建应用程序的整个过程:从 UI 设计,到编写业务逻辑,再到测试。
AngularJS 使用以下术语
模块(Module):一个逻辑组件,可用于逻辑地分组组件。它可以作为 AngularJS 引导的参数。它可以创建为
var myApp=angular.module("MyAngularApp"[<comma separarated list of dependencies>]);
//example var myApp=angular.module("MyAngularApp",['ngAnimate','ui-router']);
控制器(Controller):一个 JavaScript 组件,可以监听 HTML 视图上执行的操作,并包含包含逻辑的 JavaScript 代码。它可以创建为
angular.module("MyAngularApp").controller("UserCtrl",["$scope",function($scope)
{
//code specific to this controller goes here.
}]);
指令(Directive): AngularJS 中用于任何 DOM 操作的组件。在 Angular 中,我们无法直接从指令以外的任何其他组件与 DOM 进行交互。我们可以创建指令为
angular.module("MyAngularApp").directive("userwidget",["$scope",function($scope)
{
return{
restict:'A',
link:function(scope,elem,attrs){
}
};
}]);
有关指令的更多详细信息,请参阅 AngularJS 网站上的指令部分。
服务/工厂(Services/Factories): 通常用于定义一些单例对象的特定组件,这些对象用于与服务器通信以从服务器获取和发送 JSON 数据。它们可以定义为
angular.module("MyAngularApp").factory("UserService",['$http',function($http)
{
var Service={};
Service.getUsers=function()
{
//code to get the user list from the server using Angular $http Service and return a promise
}
}]);
还有其他方法可以访问服务器上的资源,其中一种方法是使用 AngularJS 中提供的 $resources 服务。您可能会想,为什么 AngularJS 团队引入了两样东西来完成相同的从服务器获取数据的工作。实际上,$resources 服务更面向 REST,它内部使用 $http。
提供者(Providers): 提供者位于 AngularJS 框架的核心。根据 AngularJS 文档,“Provider 是一种核心的创建方式,所有其他创建方式都只是在其之上的语法糖。它是最冗长的创建方式,功能最强大,但对于大多数服务来说都过于繁琐。Provider 方式是通过实现一个 $get
方法的自定义类型来定义的。这个方法是一个工厂函数,就像我们在 Factory 方式中使用的那样。事实上,如果您定义了一个 Factory 方式,一个空的 Provider 类型,其 $get
方法被设置为您的工厂函数,它会在后台自动创建。” 要了解有关提供者的更多信息,请访问 AngularJS 网站。
在简要介绍了 AngularJS 之后,现在让我们将重点放在我们的核心主题上。首先,我们将讨论应用程序的整体结构及其核心组件。在深入研究这些内容之前,这里是企业级应用程序的典型文件夹结构。代码库还有许多其他组织方式,但我个人更喜欢这种方式,因为它能使代码更易于维护。
/js
../MyApp // Root folder that will hold you application
..../Module 1 // modularization
....../controllers // all controllers of a module are saved under the folder,For submodules, create folder under this.
....../directives
....../partials //this will hold the html templates for views.
....../resources // Default english locale strings file. I in my projects use Jquery Globlize lib.
....../less
....../filters
......app.js // module level configuration file, which will define the module and its routes.
..../Module 2
.
.
.
..../Module N
..../shared
....../commonHelpers // common helper services/factories that can be used across application.
....../apis //factories that will talk to external resources to get and send data.
....app.js // the main bootstrap file which defines the base module and include other module. The
place to do some application wide settings for $urlRouteProvider, $httpProvider etc
../MyAppTests
..../Unit
..../e2e
一旦应用程序代码结构到位,让我们讨论 main app.js 应该是什么样子。
angular.module("MyAppMasterModule",['Module 1',
'Module 2', ..................'Module N'])
.config(function($httpProvider)
{
//Do some application setting specific to Http Service, like if you want to send some extra
headers in each call
}).run(function($rootScope, $state, $stateParams, $window)
{
//Use this area to execute some code which you want to be executed when the application is
bootstraped.
});
在上面的代码片段中,我们可以包含任意数量的配置块。
在 SPA 中,服务器只渲染一个功能齐全的 HTML 页面,这里是一个典型的页面。
<html ng-app="MyAppMasterModule">
<head>
<title></title>
<link>
<!---load you css files here -->
</link>
<!-- load you JS library files here like angularJS, JQuery etc..
<!-- load you application specific JS files here. For a large enterprise class application, this section will typicalls have following files
MyApp-min.js or MyApp.js
MyApp-resouces.js
MyApp-templates.js
-->
</head>
<body>
<div>><!---The top header section and navbar</div>
<div ui-view><!--- the content section ---></div>
</body>
</html>
上面的模板仅用于说明基础页面应该是什么样子。第二个 `div` 上的 `ui-view` 属性是 AngularJS 指令,它将负责在执行时将模板 HTML 包含在此部分中。
为了本文的篇幅,我假设开发人员熟悉 Grunt、Bower、UglifyJS、html2Js 等工具,这些工具有助于创建上述一些文件。我将在不久的将来撰写一些关于这些工具的文章。
完成此操作后,AngularJS 将接管一切,并在模块级别的 JS 文件或 JS 中的任何路由文件中查找路由定义。
典型的模块级别 JS 文件将如下所示。
angular.module("MyAppMasterModule.Module1",[<<comma separated dependency list>>])
.config(function ($stateProvider, $urlRouterProvider)
{
$stateProvider
.state('state1', {
abstract: true,
url: '/url1',
templateUrl: 'module 1/partials/statemain.html')
})
.state('state1.substate1', {
url: '/substate1',
templateUrl: 'module 1/partial/state1.html',
controller: 'Module1.state1Ctrl'
});
}
我们可以在此文件中定义许多这样的状态,并且状态甚至可以是子状态。要了解有关 ui-router 的更多信息,请参阅 https://github.com/angular-ui/ui-router。
模板或局部视图应在其各自的 HTML 文件中定义,以 `div` 开头的 HTML 容器标签开头。数据绑定可以使用 AngularJS 模板框架完成。
例如,如果我们有一个用户服务为我们提供具有 name、age、username 字段的用户列表,我们可以按以下模板显示用户列表。
<div class="user-list">
<table>
<tr>
<th>Name</th>
<th>Age</th>
<th>User name</th>
</tr>
<tr ng-repeat="user in lstUsers">
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>{{user.username}}</td>
</tr>
</table>
</div>
结论
本文旨在详细介绍使用 AngularJS 框架构建企业级单页应用程序的第一步。如前所述,未来我将撰写更多关于使用能够简化开发人员生活的 JavaScript 工具的文章。
我还会专门用一篇文章来讲解 AngularJS 代码的单元测试。
我希望大家都能从本文中受益,并欢迎任何评论或建议。