引用自:http://www.revillweb.com/tutorials/angularjs-in-30-minutes-angularjs-tutorial/,翻译如下:
简介
我三年前开始使用 AngularJS,那时它还是一个新鲜事物。 现在 AngularJS已经成为了一个最受欢迎的 JavaScript 框架之一,多亏了AngularJS 团队作出的努力。
这个教程使用的是1.3.4版本,涵盖非常基础东西,但是都是在使用过程中总结出来的最佳实践经验。
开始
开始前,你先创建一个文件夹,命名为 angularjs-tutorial
,然后在文件夹中建立下面几个文件,文件目录结构如下:
- angularjs-tutorial
| - main.ctrl.js
| - app.js
| - index.html
打开 index.html
文件,输入一下简单的 HTML内容,文件头部引用来自其它站点CDN的 AngularJS文件和 Twitter Bootstrap样式文件。我们准备使用 Twitter Bootstrap 作为 CSS 框架,这样会让我们更容易更快地创建视图布局,可以让我们将注意力放在 AngularJS上面。如果你想了解更多 Twitter Bootstrap 有关的知识,请点击我的相关教程 Twitter Bootstrap Tutorial。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS Tutorial</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script> <script src="app.js"></script> <script src="main.ctrl.js"></script> </head> <body> </body> </html>
这些 HTML 代码也引用了我们自己创建的 app.js
和main.ctrl.js
文件。
让你的网页Angular化
在我们的 app.js
我们要先搞一个 AngularJS module 出来用在我们的app里面。复制下面的代码到 app.js
angular.module('app', []);
这个 angular.module()
函数用作angular module的 setter 和getter 。第一个参数是 module 的名称,我们起名为 app
, 第二个参数我们提供了一个数组。如果给出了一个数组,那么angular会创建并取得相应的app module,稍后我们创建自己的controller你就可以看到。
现在我们需要告诉angular,我们想将这个module用在什么地方,打开 index.html
,将 ng-app='app'
添加到 <body>
标签,如下所示:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS Tutorial</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script> </head> <body ng-app="app"> </body> </html>
这里告诉了angular ,所有在body里面的东西都是我们 AngularJS application 的一部分,我们这里的AngularJS application 命名为 app
.
控制器 controller
AngularJS 提供一种宽松的 MVC 结构,更准确来说是 MVVM 模式。控制器是你处理业务逻辑的地方,本质上来说,控制器是用来控制数据并且将数据提供给视图用于显示的东西。 为了声明我们的 controller,打开 main.ctrl.js
文件,将下面的代码添加进去。
angular.module('app').controller("MainController", function(){ var vm = this; });
在声明的代码中,我们首先获取了一个 我们之前声明的app module,然后用 controller
函数初始化一个新的controller。这个 controller
函数有两个参数,第一个参数是控制器名称,第二个参数是一个函数,这个函数是用来放我们的控制代码的,我们要实现的功能就是写在这个函数里面。
在我们使用这个控制器前,我们需要告诉 angular那部分HTML 代码是属于这个控制器管理的。在一个html文档中,你可以有很多个控制器,并且可能有多个控制器管理同一段html代码,控制器之间甚至可以嵌套。在我们非常简单的例子中,我们准备只用一个控制器来管理这个页面好了。我们可以用 controllerAs
语法来声明(等一下再细说),打开 index.html
,将下面代码放在 body 标签。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS Tutorial</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script> </head> <body ng-app="app" ng-controller="MainController as main"> </body> </html>
理解 scope
通常来说你可以将 $scope
注入到controller,然后将全部controller变量分配到这个scope对象,这样这些变量就可以在html使用了。 然后,更好的途径,被AngularJS团队推荐的做法是使用 controllerAs 。这种方式提供了更 semantic 的途径在html中去声明 controllers ,并且防止当 multiple-nested controllers 出现的时候诸如 scope bleed 的问题。
我们将一个 controller 实例分配到变量 vm
中,这个变量代表了 ViewModel ,在 John Papa的文章 style guide 中 推荐这样做。我们将分配所有需要在view中可访问的控制器变量到这个对象,这样angular 就可以起到诸如双向绑定等魔法般的作用了。
为了理解scope,我们声明一个简单的变量 title
,用来保存在我们页面上要显示的标题。打开 main.ctrl.js
添加下面的代码。
angular.module('app').controller("MainController", function(){ var vm = this; vm.title = 'AngularJS Tutorial Example'; });
为了在我们的页面显示这个标题文本,我们使用下面的语法。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS Tutorial</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script> </head> <body ng-app="app" ng-controller="MainController as main"> <div class="container"> <h1>{{main.title}}</h1> </div> </body> </html>
在上面的例子中,我们使用了两对花括号{{}}将title显示在h1标签中,两对花括号可以让 angular 知道这是个变量。 之前我们用MainController as main来声明了一个控制器的别名,
我们通过用控制器的别名main加变量来访问控制器 scope 里面的变量title,如{{main.title}}。现在想一下,如果我们一个文档中有几个不同的 controller,你如果不用别名加变量的形式,而是直接写{{title}},那么你将很难区分那个变量是属于哪个控制器的。另外,如果不同的控制器里面有相同名称的变量,那么问题就更严重了
(例如: scope bleed).
如果你在一个网页打开 index.html
,你可以看到一个无聊title 的文本显示在网页上面。
理解绑定
双向绑定是 AngularJS 的主要卖点之一。让我们看一下什么情况。在main.ctrl.js
中增加一个变量 searchInput
如下:
angular.module('app').controller("MainController", function(){ var vm = this; vm.title = 'AngularJS Tutorial Example'; vm.searchInput = ''; });
打开 index.html
,添加一个简单的输入框:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS Tutorial</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script> <script src="app.js"></script> <script src="main.ctrl.js"></script> </head> <body ng-app="app" ng-controller="MainController as main"> <div class="container"> <h1>{{main.title}}</h1> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-search"></span> </span> <input type="text" class="form-control" ng-model="main.searchInput"> </div> <p>{{main.searchInput}}</p> </div> </body> </html>
除此以外添加双重花括号包住 searchInput
变量,这样输入框的值就显示在双重花括号的位置。在输入框中我们添加一个 ng-model
属性,并指定值为 searchInput
,这个值就是来自main controller的searchInput变量。 现在输入框绑定了同名的变量,它可以受控制器管理。 如果你在浏览器打开index.html
页面,在输入框中输入内容,你可以立刻看到{{main.searchInput}}的位置显示出文本框的内容。
使用 ngRepeat
AngularJS 提供很多内建的指令方便你完成常见的功能。ngRepeat 指令可让你枚举一个集合,然后显示在页面上。我们建一个数组来试一下。把 main.ctrl.js
改为下面这样。
angular.module('app').controller("MainController", function(){ var vm = this; vm.title = 'AngularJS Tutorial Example'; vm.searchInput = ''; vm.shows = [ { title: 'Game of Thrones', year: 2011, favorite: true }, { title: 'Walking Dead', year: 2010, favorite: false }, { title: 'Firefly', year: 2002, favorite: true }, { title: 'Banshee', year: 2013, favorite: true }, { title: 'Greys Anatomy', year: 2005, favorite: false } ]; });
现在我们有了一个数组,可以使用ngRepeat来遍历展示每一项数据。打开 index.html
添加如下代码:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS Tutorial</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script> <script src="app.js"></script> <script src="main.ctrl.js"></script> </head> <body ng-app="app" ng-controller="MainController as main"> <div class="container"> <h1>{{main.title}}</h1> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-search"></span> </span> <input type="text" class="form-control" ng-model="main.searchInput"> </div> <h3>A list of TV shows</h3> <ul class="list-group"> <li class="list-group-item" ng-repeat="show in main.shows">{{show.title}} <span class="badge">{{show.year}}</span></li> </ul> </div> </body> </html>
在这个例子ngRepeat会复制列表的项,然后绑定数组的数据展示到页面。我们可以用 {{show.[property]}}
读取每一项的属性,然后去展示在<li>元素中。
隐藏和显示元素
其它AngularJS 指令可以让你用判断和表达式来显示和隐藏html元素、这些指令是 ngHide, ngShow, ngSwitch & ngIf。甚至通过这些指令达到相似的目的,这对于某些情况很有用。ngSwitch 指令很有用,当你碰到条件判断是,例如单选框切换。 ngHide, ngShow 和 ngIf 很相似。ngIf 会移除受影响的元素, ngHide 和 ngShow 只是增加一个 display: none;
样式值来隐藏元素。
因此 ngIf 比 ngHide, ngShow等命令会节省一些内存。 ngHide 和 ngShow在有动画效果的隐藏和显示会好一些,ngIf会影响动画的效果。
在下面例子中,我们用ngIf指令我们被标记为喜欢的每一个列表项前面添加带一个星星图标:
<h3>A list of TV shows</h3>
<ul class="list-group">
<li class="list-group-item" ng-repeat="show in main.shows"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li>
</ul>
当 show.favorite
的值为true的时候列表的元素增加了一个星星图标ng-if的值是一个表达式,所以也可以这样写
show.favorite == true
或者 show.favorite != false
在ngRepeat中使用过滤器
用AngularJS 很容易实现过滤筛选ngRepeat里面的条目。
<h3>A list of TV shows</h3> <ul class="list-group"> <li class="list-group-item" ng-repeat="show in main.shows | filter:main.searchInput"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li> </ul>
使用ng-repeat="show in main.shows | filter:main.searchInput"就行了,
很容易对吧。
来复杂一点的,增加几种排序功能。 改一下main.ctrl.js,列出排序的几种类型。
vm.orders = [ { id: 1, title: 'Year Ascending', key: 'year', reverse: false }, { id: 2, title: 'Year Descending', key: 'year', reverse: true }, { id: 3, title: 'Title Ascending', key: 'title', reverse: false }, { id: 4, title: 'Title Ascending', key: 'title', reverse: true } ]; vm.order = vm.orders[0];
现在增加一个选择菜单到 index.html
,用户可以用来选择不同的排序,然后增加一个过滤器到我们上面添加的 ngRepeat 。
<body ng-app="app" ng-controller="MainController as main"> <div class="container"> <h1>{{main.title}}</h1> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-search"></span> </span> <input type="text" class="form-control" ng-model="main.searchInput"> </div> <h3>A list of TV shows</h3> <ul class="list-group"> <li class="list-group-item" ng-repeat="show in main.shows | filter:main.searchInput | orderBy:main.order.key:main.order.reverse"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li> </ul> <select class="form-control pull-right" ng-model="main.order" ng-options="order as order.title for order in main.orders"></select> </div> </body>
在上面,我们已经增加了一个 orderBy
过滤器到 ngRepeat ,而且我们指定了用来排序的哪个属性,在这个例子中我们用title来排序。然后我们指定了排序的方向,这个例子中我们我们用了逆向排序
reverse。
为了组装好选择菜单,我们使用 ngOptions 指令,点击 这里 你可以了解更多
在菜单中,改变选中的值,体验一下吧。
表单检验
从表单中收集用户数据是网页应用开发的重点之一。AngularJS 使表单验证变得很容易。 在下面这个简单的例子中,我们会创建一个表单允许用户添加一个新的节目到节目列表中。打开 index.html
代码,添加下面的内容
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS Tutorial</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script> <script src="app.js"></script> <script src="main.ctrl.js"></script> </head> <body ng-app="app" ng-controller="MainController as main"> <div class="container"> <h1>{{main.title}}</h1> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-search"></span> </span> <input type="text" class="form-control" ng-model="main.searchInput"> </div> <h3>A list of TV shows</h3> <ul class="list-group"> <li class="list-group-item" ng-repeat="show in main.shows | filter:main.searchInput | orderBy:main.order.key:main.order.reverse"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li> </ul> <select class="form-control pull-right" ng-model="main.order" ng-options="order as order.title for order in main.orders"></select> <div class="clearfix"></div> <h3>Add a new TV Show</h3> <form name="main.addForm" class="form"> <div class="form-group"> <label>Title</label> <input type="text" class="form-control" ng-model="main.new.title" required /> </div> <div class="form-group"> <label>Year</label> <input type="number" min="1900" max="2030" class="form-control" ng-model="main.new.year" required /> </div> <div class="row"> <div class="col-xs-6"> <label>Favorite: <input type="checkbox" ng-model="main.new.favorite" /></label> </div> <div class="col-xs-6"> <button class="btn btn-success pull-right"><span class="glyphicon glyphicon-plus-sign"></span> Add</button> </div> </div> </form> </div> </body> </html>
这个简单的表单允许用户输入一个节目标题、年份以及指定此节目是否是否是自己喜欢的。在标题和年份字段我们增加了一个 required
属性用来指定这个字段是必填的。另外我们还指定了年份字段的类型为 number
,限制只能输入数字,我们还增加了 min
和 max
属性用来限制输入数字的大小范围。当用户点击添加按钮是,会自动给用户实时反馈。如果用户没有在必填字段中输入内容,会提示一个错误消息。另外如果用户输入的数字不在1900到2030范围内,也会有相应的错误提示。自己试一下吧。
了解更多关于AngularJS表单的知识,请点击 这里
简单的事件响应
在教程最后的一部分,讲一下AngularJs的事件吧。 事件在Js框架当中总是处于很重要的地位,即使是对于AngularJs的双向绑定来说
在 MainController底部添加如下代码:
vm.new = {}; vm.addShow = function() { vm.shows.push(vm.new); vm.new = {}; };
上面的代码声明了一个叫做new的对象,表单用来存放来自ngModel输入的值 (例如 ng-model="main.new.year"
)。另外 addShow
函数用来将 new 对象放到 shows 数组,然后添加到视图上的列表。
AngularJS 提供了多种时间指令例如ngClick, ngChange, ngFocus, 等待。我们可以用来相应各种动作。在我们的例子我们使用ngSubmit 指令在表单被成功提交后触发调用 addShow
函数。打开 index.html,增加相应的指令代码:
<form name="main.addForm" class="form" ng-submit="main.addShow()">
现在,当表单通过验证后,用户点击按钮, addShow
函数就会被调用,新的节目就会显示到界面上的节目单上面。
这是一个AngularJs提供的一个非常简单的例子,如果想了解更多请查看相关文档 。
结语
在这个快速入门教程里, 你现在应该掌握了几个AngularJS 概念,你可以用这些知识搭建一下简单的网页应用了。 AngularJS 提供了更多功能,在30分钟的教程里我很难一一列举,如果你喜欢这个教程,请到原文中订阅,随时获得最新的更高级的教程。
(终于翻译完了,可能有一些错误字和一些不通顺的语义,请大家见谅)