本文翻译自这里。
翻译过程中加入了译者本人的理解,并作了适当的筛减。
简介
创建一个简单的邮件应用程序,学习核心的AngularJS概念。在结束该教程的学习时,你将能够看到(虚构的)邮件应用程序,在该程序中,可以根据邮件主题查询邮件,还可以阅读或删除邮件。
学习的先决条件:
- 会使用jQuery创建简单的JavaScript应用
- 懂得如何启动简单的HTTP服务器(如 python -m SimpleHTTPServer)
- 会从Github上克隆一个项目
涵盖的主题
- 单页面应用(SPA)
- 客户端MVC模式
- 双向数据绑定
- 路由与模板
- AngularJS构建块:指令标签(Directives),工厂(Factories)以及控制器(Controllers)
客户端MVC
- 模型(Model):可以说是数据;一个应用的业务信息;
- 视图(View):HTML和数据的呈现。是用户所见到和交互的界面;
- 控制器(Controller):让应用中的所有不同模块协同工作的连接器。
开始使用AngularJS
在页面中引入AngularJS
在HTML页面的底部<body>结束标签之前引入AngularJS的.js文件。
<html> <head> </head> <body> <div></div> <script src="lib/jquery-v1.11.1.js"></script> <script src="lib/angular-v1.2.22.js"></script> </body> </html>
Angular自身内置了一个叫做“jQLite”的东西,它是一个类似jQuery的微型库。jQLite是一个非常轻量级的库,因此也就没有你可能需要的强大的jQuery方法。这里引入jQuery主要是出于可能后续会引入一些依赖于jQuery库的插件。
设置作用域(Scopes)和指令标签(Directives)
Angular非常基础的一个概念是作用域(scopes)。Scopes保存着你的Models(也就是你的数据),它与你的控制器(Controllers)一起协作,同时为视图(Views)提供了所需的一切。Angular的scopes概念与常见的JavaScript中的作用域(scope)概念非常相似。
第一步是需要设置整个应用的作用域,它标识出了Angular应用起作用的范围。通常我们会在<html>标签中通过ng-app属性来设置它。
<html ng-app="myApp"> <head></head> <body></body> </html>
另外一个与scope相关的指令是ng-controller,它决定了一个控制器的作用域范围。在一个应用中可以包含多个控制器。每个控制器都有其自身的作用域范围。
<div ng-controller="InboxCtrl"> <!-- inside InboxCtrl scope --> </div>
ng-app和ng-controller都是Angular指令标签。可以把Angular指令标签看作是对HTML的扩展。
你的第一个控制器:一个简单的例子
把我们刚刚学到的用在实践中
1 创建一个空的HTML文档
2 引入Angular和jQuery文件
<script src="lib/jquery-v1.11.1.js"></script> <script src="lib/angular-v1.2.22.js"><script>
3 在<html>标签中添加ng-app="myApp"
4 在body中创建一个控制器示例
<div ng-controller="TestCtrl"><h1></h1> <input type="text" ng-model="title"> </div>
稍后我们会解释ng-model="title"的含义。
5 创建内嵌的JavaScript脚本,确保该脚本在所引用库文件之后。
<script> function TestCtrl($scope) { $scope.title = 'Write a title here...'; }; </script>
是否已发现函数的名字跟ng-controller的值是一样的?Angular会在JavaScript中寻找相同名称的函数来作为控制器。
以下是完整的代码:
<!doctype html> <html ng-app> <head> <title>Sample AngularJS Controller</title> </head> <body> <div ng-controller="TestCtrl"> <h1></h1> <input type="text" ng-model="title"> </div> <script src="lib/jquery-v1.11.1.js"></script> <script src="lib/angular-v1.2.22.js"></script> <script> function TestCtrl($scope) { $scope.title = 'Write a title here...'; }; </script> </body> </html>
ngView与路由(Routes)
将URL与作用域关联
另外一个重要的构建块是ng-view指令标签,它能够将应用中的某个URL关联到作用域中。
<html ng-app="myApp"> <head> </head> <body> <div ng-view></div> </body> </html>
这里的ng-view标签能够根据用户访问的URL告诉Angular我们想插入的HTML。
模块(Modules)
angular.module()
每个应用需要一个模块,而Angular通过angular.module()为我们提供了模块命名空间的能力。该方法既可以设置模块也可以获取一个模块,关键取决于如何使用它。创建(设置)一个新的模块,如:
angular.module('myApp', []);
获取一个模块的引用,用以注册controllers,factories,filters等,可以不用后面的那个数组而只需通过模块的名称:
angular.module('myApp');
路由(Routing)与依赖注入(Dependency Injection)
路由
接下来是配置路由,路由使应用能够根据我们访问的URL来确定加载哪个视图。
RouteProvider
从Angular 1.2.0版本开始,核心的Angular中不在包含$routeProvider,因此需要将其作为一个独立的模块引入(angular-route.js)。
<body> <!-- ... --> <!-- Extra routing library --> <script src="lib/angular-route-v1.2.22.js"></script> </body>
该文件为我们提供了一个名为ngRoute的模块,在我们自己的模块定义的时候需要将其作为依赖引入:
var app = angular.module('app', [ 'ngRoute' ]);
配置阶段
Angular中每个模块具有一个.config()方法,可以给该方法传入一个回调函数,该回调函数将在很多其他函数执行前调用。就是在这个地方配置我们的路由:
app.config(function () {/*...*/});
依赖注入
在config回调函数中,我们需要$routeProvider来配置路由,可以简单地把$routeProvider作为config函数的参数传入,剩下的事情交由Angular处理。
app.config(function ($routeProvider) { /* Now we can use the routeProvider! :D */ });
配置路由
app.config(function ($routeProvider) { $routeProvider .when('/inbox', { templateUrl: 'views/inbox.html', controller: 'InboxCtrl', controllerAs: 'inbox' }) .when('/inbox/email/:id', { templateUrl: 'views/email.html', controller: 'EmailCtrl', controllerAs: 'email' }) .otherwise({ redirectTo: '/inbox' }); });
控制器(Controllers)
连接模型与视图
一个好的控制器只包含尽可能少的逻辑在里面,且只完成两项工作:将模型绑定到视图(初始化视图);为视图添加帮助函数。
app.controller('InboxCtrl', function () { // Model and View bindings // Small helper function not needed anywhere else });
每个控制器都能够访问$scope。通过$scope可以往视图上添加属性和方法。
app.controller('InboxCtrl', function ($scope) { // initialize the title property to an array for the view to use $scope.title = "This is a title"; });
在标签中可以这样与之对应:
<div ng-controller="InboxCtrl"> {{ title }} </div>
工厂(Factories)
工厂常用于通过HTTP与服务端交互。
可以通过angular.factory()方法创建一个工厂,如:
app.factory('ExampleFactory', function ExampleFactory($rootScope, $http, $location) { return function myReusableFunction() { // do something fancy }; });
在该应用中,需要获取邮件信息,可以创建一个方法来实现。Angular使用$http服务来与服务端交互,因此需要将它也引入:
app.factory('InboxFactory', function InboxFactory ($http) { var exports = {}; exports.getMessages = function () { return $http.get('json/emails.json') .error(function (data) { console.log('There was an error!', data); }); }; return exports; });
关联工厂与控制器
app.controller('InboxCtrl', function($scope, InboxFactory) { InboxFactory.getMessages() .success(function(jsonData, statusCode) { console.log('The request was successful!', statusCode, jsonData); // Now add the Email messages to the controller's scope $scope.emails = jsonData; }); });
模板(Templating)
视图渲染
<!-- JavaScript inside expression --> <h1>{{ [ firstName, lastName ].join(" ") }}</h1> <!-- currency filter applied to a multiplication of 2 numbers --> <div class="total-info">{{ cost * quantity | currency }}</div> <!-- Using a ternary expression inside the expression --> <div class="budget">{{ ( total > budget ) ? "Too Expensive" : "You can buy it!" }}</div>
指令标签概览
自定义HTML标签
指令标签是Angular提供的自定义HTML标签,它为封装数据、模板与行为提供了一种可重用的方式。
在我们的视图中,有时可以见到如下的标签:
<div id="someview"> {{ data.scopePropertyAsUsual }} <my-custom-element></my-custom-element> </div>
上面的<my-custom-element>标签会被我们定义的标签模板和逻辑替代。以下为一个简单的指令标签结构示例:
app.directive('myCustomElement', function myCustomElement() { return { restrict: 'EA', replace: true, scope: true, template: [ "<div>", " <h1>My Custom Element's Heading</h1>", " <p>Some content here!</p>", " <pre>{{ ctrl.expression | json }}</pre>," "</div>" ].join(""), controllerAs: 'ctrl', controller: function ($scope) { this.expression = { property: "Example" } }, link: function (scope, element, attrs) {} } });
工厂与指令协同工作
angular.module('EmailApp') .factory('InboxFactory', function InboxFactory ($q, $http, $location) { 'use strict'; var exports = {}; exports.messages = []; exports.goToMessage = function(id) { if ( angular.isNumber(id) ) { // $location.path('inbox/email/' + id) } } exports.deleteMessage = function (id, index) { this.messages.splice(index, 1); } exports.getMessages = function () { var deferred = $q.defer(); return $http.get('json/emails.json') .success(function (data) { exports.messages = data; deferred.resolve(data); }) .error(function (data) { deferred.reject(data); }); return deferred.promise; }; return exports; });
app.directive('inbox', function () { return { restrict: 'E', replace: true, scope: true, templateUrl: "js/directives/inbox.tmpl.html", controllerAs: 'inbox', controller: function (InboxFactory) { this.messages = []; this.goToMessage = function (id) { InboxFactory.goToMessage(id); }; this.deleteMessage = function (id, index) { InboxFactory.deleteMessage(id, index); }; InboxFactory.getMessages() .then( angular.bind( this, function then() { this.messages = InboxFactory.messages; }) ); }, link: function (scope, element, attrs, ctrl) { /* by convention we do not $ prefix arguments to the link function this is to be explicit that they have a fixed order */ } } });
用于上述指令标签的完整HTML模板:
<div class="inbox"> <div class="inbox__count"> You have {{ inbox.messages.length && inbox.messages.length || 'no' }} messages </div> <div ng-hide="!inbox.messages.length"> <input type="text" class="inbox__search" ng-model="inbox.search" placeholder="Search by 'from', e.g. TicketMaster"> </div> <ul class="inbox__list"> <li ng-show="!inbox.messages.length"> No messages! Try sending one to a friend. </li> <li ng-repeat="message in inbox.messages | filter:{ from: inbox.search }"> <div class="inbox__list-info"> <p class="inbox__list-from"> from: {{ message.from }} </p> <p class="inbox__list-date"> {{ message.date | date: 'dd/MM/yyyy' }} </p> <p class="inbox__list-subject"> {{ message.subject }} </p> </div> <div class="inbox__list-actions"> <a href="#" ng-click="inbox.goToMessage(message.id);"> Read </a> <a href="" ng-click="inbox.deleteMessage(id, $index);"> Delete </a> </div> </li> </ul> </div>
内置指令标签
ng-show, ng-repeat, ng-click
<ul> <li ng-repeat="item in items"> {{ item.name }} </li> </ul>
<li ng-repeat="message in inbox.messages | filter:{ from: inbox.search }">
<input type="text" class="inbox__search" placeholder="Search" ng-model="inbox.search">
相关推荐
Tutorialspoint AngularJS教程.epub
AngularJS中文使用教程,简体中文
w3school AngularJS教程 飞龙整理 20141001
angularjs, 面向AccioCode的AngularJS教程 Accio代码教程: AngularJS#更新:2 -10-16本系列针对 AccioCode插件的教程将展示如何使用AngularJS的基本特性。 你将学习如何制作简单的网页和简单的web应用程序。什么是 ...
这是AngularJS教程,写的比较详细
angularjs教程,可以看看
我看过讲得最详细的angularjs教程
36讲AngularJs+ionic视频教程,适合有基础的同学,加油
thinkster-django-angular-tutorial, Thinkster.io Django 和AngularJS教程的Markdown 文件 thinkster-django-angular-tutorial在本教程中,你将使用 Django 和AngularJS构建一个名为"不是Google加"的简化Google+...
AngularJS
本文主要介绍AngularJS简单应用程序,这里提供了详细的流程和代码程序,有需要的小伙伴可以参考下
来自w3school 的angularjs完整版教程,制作成了epub,简体中文,有目录,排版精美,适合下载到移动设备离线阅读.
精心收藏 节省大家时间 提高大家效率 提高大家效率 提高大家效率
AngularJS 完整指南YN Pamungkas Jayuda @2014 ThinkBuntu初步的欢迎来到 AngularJS 教程。 AngularJS 是一个客户端 javascript 框架。 AngularJS 通常由擅长 javascript 的程序员使用。 关于 AngularJS 的教程很多...
angularjs课程实例,如控制器、指令、双向数据绑定、过滤器、路由等。
相对权威的资料,能够为初学者带来比较不错的收益,希望大家共同进步
Python3教程菜鸟教程 教程菜鸟教程 ADO 教程 Ajax 教程 Android 教程 AngularJS 教程 AngularJS2 教程 AppML 教程 ASP 教程 ASP.NET 教程 Bootstrap 教程 C 教程 C# 教程 C++ 教程 CSS 参考⼿册 CSS 教程 CSS3 教程 ...