本文翻译自这里。
翻译过程中加入了译者本人的理解,并作了适当的筛减。
简介
创建一个简单的邮件应用程序,学习核心的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">
相关推荐
这篇“AngularJS中文教程”涵盖了AngularJS的基础到进阶内容,对于想要学习或深入理解AngularJS的开发者来说,是一份非常有价值的资源。教程以简体中文呈现,方便中国开发者阅读和理解。 1. **双向数据绑定**:...
Tutorialspoint AngularJS教程.epub
angularjs, 面向AccioCode的AngularJS教程 Accio代码教程: AngularJS#更新:2 -10-16本系列针对 AccioCode插件的教程将展示如何使用AngularJS的基本特性。 你将学习如何制作简单的网页和简单的web应用程序。什么是 ...
这是AngularJS教程,写的比较详细
angularjs教程,可以看看
36讲AngularJs+ionic视频教程,适合有基础的同学,加油
thinkster-django-angular-tutorial, Thinkster.io Django 和AngularJS教程的Markdown 文件 thinkster-django-angular-tutorial在本教程中,你将使用 Django 和AngularJS构建一个名为"不是Google加"的简化Google+...
AngularJS是一个由谷歌维护的开源前端JavaScript框架,用于构建动态网页应用程序。它通过使用HTML作为模板语言,引入了数据绑定、依赖注入、多组件支持等特性,从而简化了前端开发。本文将通过一个简单示例程序来...
AngularJS
来自w3school 的angularjs完整版教程,制作成了epub,简体中文,有目录,排版精美,适合下载到移动设备离线阅读.
精心收藏 节省大家时间 提高大家效率 提高大家效率 提高大家效率
AngularJS,里面包含AngularJS各种教程,如下: AngularJS- Novice to Ninja.pdf AngularJS Test-driven Development.pdf AngularJS- Up and Running.pdf AngularJS Web Application Development Cookbook.pdf ...
AngularJS 是一款由 Google 推出的开源JavaScript框架,主要用于构建单页面应用程序(Single Page Applications, SPAs)。这个框架的设计目标是简化前端开发,提供一种更加直观的方式来处理动态内容和数据绑定,使...
AngularJS 完整指南YN Pamungkas Jayuda @2014 ThinkBuntu初步的欢迎来到 AngularJS 教程。 AngularJS 是一个客户端 javascript 框架。 AngularJS 通常由擅长 javascript 的程序员使用。 关于 AngularJS 的教程很多...
这个实例教程将带你深入理解AngularJS的核心概念和技术,包括控制器、指令、双向数据绑定、过滤器和路由,这些都是AngularJS开发中的关键元素。 首先,我们来详细讨论一下每个知识点: 1. **控制器**:在AngularJS...
通过阅读《angular快速教程.doc》、《angularjs基础教程(经典).doc》、《angularjs教程(经典)含node.js安装.doc》以及《angularjs案例教程.doc》,你将逐步掌握AngularJS的方方面面,并学会在Node.js环境下开发和...
AngularJS教程之MVC体系结构详解涵盖了AngularJS框架中的核心概念模型-视图-控制器(MVC)设计模式。MVC是一种广泛使用的软件设计模式,尤其适用于Web应用程序的开发,目的是将数据处理、用户界面和用户输入这三部分...
"pixltalk-2015:用 AngularJS 编写的 AngularJS 教程" 提供了一个学习和探索 AngularJS 框架的资源。这个教程可能涵盖了上述的所有概念,包括AngularJS的核心特性如数据绑定、指令系统、依赖注入,以及模块化、控制...