AngularJS in Action读书笔记1——扫平一揽子专业术语
前(fei)言(hua):
数月前,以一个盲人摸象的姿态看了一些关于AngularJS的视频书籍,留下了我个人的一点或许是指点迷津或许是误人子弟的读后感。自以为已经达到熟悉ng的程度,但是因为刚入公司,没法直接接触代码层面的编程,日子一天天过去,ng在我脑海的残留也一天天的模糊……
数月后,我重返ng战场,艰难的收集之前留下的记忆碎片,一番拼接下来,没有让我对ng的理解串成一条线,反而支离破碎的片段scope、template、directive、controller、config、factory、service、provide、compile、link、this.$get,让我不得不重新正视它。
简而言之,以前的理解是针对某个点或者面,但是如果只停留在这个角度,在阅读理解项目代码时经常犯晕,一个偶然的机会,我看到了《AngularJS in action》,虽然看到的是英文版,但是看了几页之后觉得思路清晰,讲解深入浅出,我就一路看下来,并且正在继续(就我所知,目前市面上应该还没有中文版本)。下面所写内容多数来源于此书。
下载链接:http://download.csdn.net/detail/zhengjie_1990/9416066
有关AngularJS的介绍在前面系列文章《AngularJS入门心得1——directive和controller如何通信》篇中有提到,这里不再赘述。相较已经发展很成熟也很成功的jQuery来说,AngularJS是一门方便维护、高可扩展、可测试的前端开源框架。
AngularJS的亮点:
1.代码组织结构清晰
AngularJS模块划分明确,不同的代码有其明确的存放处,可读性强,便于维护和扩展(后面会有代码组织结构图)。
2.功能模块易测试
AngularJS的代码方便测试。虽然代码易测试不能成为一个框架闪光的决定性因素,但是反向思考,如果写出来的代码可测试性差将会使工作效率事倍功半。
3.双向绑定
双向绑定的出现,无可争议的大大简化了你的代码量,与其说是技术的革新,不如说是一场思想上的颠覆与突破。回想jQuery还需要通过在DOM中找到需要的元素并在其上添加事件监听,通过触发事件(如点击等)才能解析获取DOM元素中的值。而在AngularJS中只需要将DOM中的元素与js的某个属性绑定,js属性值变化会同步到DOM元素上,同样的,DOM元素值得变化也会映射到js的属性上。夸张点说,一个是刀耕火种,一个是蒸汽驱动。
4.弥补HTML的先天不足
HTML本身能呈现的很有限。举个例子:好比还没有解放的中国,那时只有小米加步枪,所以每一场战役都打的很艰辛,后来解放了,改革开放了,国民经济迅猛发展,靠我们自己勤劳的双手丰富了我们的武器库国防库,我们这时候有了航母、预警机、五代隐形战机等等,我们可以呈现的东西就更多更丰富了。
这里的“小米加步枪”就是原生的HTML,局限性很大,只能打游击,很难正面交锋。但是勤劳智慧的人民就像AngularJS,我们可以创造更多种多样的指令(武器),来保卫我们的祖国,“呈现”更强大的民族。
AngularJS专业术语概览
名称 |
作用 |
Module |
AngularJS中一切都是从Module模块开始的,模块是组织代码的容器,当然模块中还可以包含子模块 |
Config |
Config是用在AngularJS application还未启动前的一些参数配置,比如路由或是一些service的配置 |
Routes |
路由负责在应用中基于state进行页面的跳转 |
Views |
Views是通过AngularJS编译后呈现的DOM |
$scope |
$scope是连接controller和view之间的桥梁,起到一种胶水的作用 |
Controller |
定义一些属性和方法用于绑定到view的元素上,一般来说,controller是比较轻量的,它里面只放一些负责view呈现的属性和方法 |
Directive |
指令使得AngularJS能够创建自定义的标签并实现相应的功能,可以将指令看成一种特殊的html标签 |
Service |
Service负责提供一些通用的功能函数,比如有些数据在多个controller中都会用到,就可以定义在一个service中 |
书中的实例
书中提供了一个实例Angello,托管在github上面,这也是我比较欣赏的地方,很方便,git pull下来只要几步就可以轻松运行起来。书中首先是提供了Angello的一个简化版本Angello-lite。
托管地址:https://github.com/angularjs-in-action/angello-lite
麻雀虽小,五脏俱全。对应于上图的AngularJS结构,该项目的组织结构如下
图中:
(1) index.html代表了view层,负责呈现;
(2) story是一对标签,代表了指令层,其写在view的index.html中;
(3) MainCtrl是controller层,其中定义了一些方法等;
(4) AngelloModel是service层,其中定义了一些公用数据等;
(5) $scope是view和controller之间的桥梁。
下面一一介绍各个部分的作用
1. Module
module是AngularJS中用来组织代码的逻辑单元。本例中,创建了一个Angello的模块并赋值给变量myModule。
代码中第一行就是创建module
var myModule = angular.module('Angello', []);
app.js
var myModule = angular.module('Angello', []); myModule.factory('AngelloHelper', function() {
var buildIndex = function (source, property) {
var tempArray = []; for (var i = 0, len = source.length; i < len; ++i) {
tempArray[source[i][property]] = source[i];
} return tempArray;
}; return {
buildIndex: buildIndex
};
}); myModule.service('AngelloModel', function() {
var service = this,
statuses = [
{name: 'Back Log'},
{name: 'To Do'},
{name: 'In Progress'},
{name: 'Code Review'},
{name: 'QA Review'},
{name: 'Verified'},
{name: 'Done'}
],
types = [
{name: 'Feature'},
{name: 'Enhancement'},
{name: 'Bug'},
{name: 'Spike'}
],
stories = [
{
title: 'First story',
description: 'Our first story.',
criteria: 'Criteria pending.',
status: 'To Do',
type: 'Feature',
reporter: 'Lukas Ruebbelke',
assignee: 'Brian Ford'
},
{
title: 'Second story',
description: 'Do something.',
criteria: 'Criteria pending.',
status: 'Back Log',
type: 'Feature',
reporter: 'Lukas Ruebbelke',
assignee: 'Brian Ford'
},
{
title: 'Another story',
description: 'Just one more.',
criteria: 'Criteria pending.',
status: 'Code Review',
type: 'Enhancement',
reporter: 'Lukas Ruebbelke',
assignee: 'Brian Ford'
}
]; service.getStatuses = function () {
return statuses;
}; service.getTypes = function () {
return types;
}; service.getStories = function () {
return stories;
};
}); myModule.controller('MainCtrl', function(AngelloModel, AngelloHelper) {
var main = this; main.types = AngelloModel.getTypes();
main.statuses = AngelloModel.getStatuses();
main.stories = AngelloModel.getStories();
main.typesIndex = AngelloHelper.buildIndex(main.types, 'name');
main.statusesIndex = AngelloHelper.buildIndex(main.statuses, 'name'); main.setCurrentStory = function (story) {
main.currentStory = story;
main.currentStatus = main.statusesIndex[story.status];
main.currentType = main.typesIndex[story.type];
}; main.createStory = function() {
main.stories.push({
title: 'New Story',
description: 'Description pending.',
criteria: 'Criteria pending.',
status: 'Back Log',
type: 'Feature',
reporter: 'Pending',
assignee: 'Pending'
});
}; main.setCurrentStatus = function (status) {
if (typeof main.currentStory !== 'undefined') {
main.currentStory.status = status.name;
}
}; main.setCurrentType = function (type) {
if (typeof main.currentStory !== 'undefined') {
main.currentStory.type = type.name;
}
};
}); myModule.directive('story', function() {
return {
scope: true,
replace: true,
template: '<div><h4>{{story.title}}</h4><p>{{story.description}}</p></div>'
}
});
(1) 其中第二个参数通过依赖注入的方式注入依赖的子模块,这样就可以在当前模块使用注入进来模块中的方法变量等。
(2) 通过这种思想,我们可以针对不同的功能模块新建不同的Module,使得代码和项目结构更加清晰。
(3) 从app.js中可以看出,Angello模块下定义了两个service AngelloModel和AngelloHelper,一个controller MainCtrl和一个directive story。
2.Views和Controllers
为了方便起见,我们将AngularJS抽象成MVVM模型来讲解。
从图中可以看出将view中的元素绑定到ViewModel上,Model会有一个提醒机制,当model值发生变化时,就会触发提醒ViewModel需要更新值了。当然,来自view端值发生改变时,也会通过ViewModel上的值改变,进而刷新model上的值。这就是双向数据绑定。
需要注意的是,要定义一个controller,需要在页面中(index.html)通过AngularJS的内置指令ng-controller进行声明。如index.html中的<h1>{{main.tite}}</h1>对应定义在controller中的title,title的任何变化都会及时的相应在index.html上。
index.html
<!DOCTYPE HTML>
<html ng-app="Angello">
<head>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<script type="text/javascript" src="app.js"></script> <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="app.css"> <title>Angello Lite</title>
</head>
<body>
<div ng-controller="MainCtrl as main">
<div class="col-md-4">
<h2>Stories</h2>
<story class="callout"
ng-repeat="story in main.stories"
ng-click="main.setCurrentStory(story)">
</story>
<br/>
<a class="btn btn-primary" ng-click="main.createStory()">
<span class="glyphicon glyphicon-plus"></span>
</a>
</div>
<div class="col-md-6 content">
<h2>Story</h2>
<form class="form-horizontal">
<div class="form-group">
<label class="control-label" for="inputTitle">Title</label>
<div class="controls">
<input type="text" class="form-control" id="inputTitle" placeholder="Title" ng-model="main.currentStory.title" />
</div>
</div>
<div class="form-group">
<label class="control-label" for="inputStatus">Status</label>
<div class="controls">
<select id="inputStatus" class="form-control" ng-model="main.currentStatus"
ng-options="l.name for l in main.statuses"
ng-change="main.setCurrentStatus(main.currentStatus)"></select>
</div>
</div>
<div class="form-group">
<label class="control-label" for="inputType">Type</label>
<div class="controls">
<select id="inputType" class="form-control" ng-model="main.currentType"
ng-options="t.name for t in main.types"
ng-change="main.setCurrentType(main.currentType)"></select>
</div>
</div>
<div class="form-group">
<label class="control-label" for="inputDescription">Description</label>
<div class="controls">
<textarea id="inputDescription" class="form-control" placeholder="Description" rows="3"
ng-model="main.currentStory.description"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label" for="inputAcceptance">Acceptance Criteria</label>
<div class="controls">
<textarea id="inputAcceptance" class="form-control" placeholder="Acceptance Criteria" rows="3"
ng-model="main.currentStory.criteria"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label" for="inputReporter">Reporter</label>
<div class="controls">
<input type="text" class="form-control" id="inputReporter" placeholder="Reporter" ng-model="main.currentStory.reporter" />
</div>
</div>
<div class="form-group">
<label for="inputAssignee">Assignee</label>
<div class="controls">
<input type="text" class="form-control" id="inputAssignee" placeholder="Assignee" ng-model="main.currentStory.assignee" />
</div>
</div>
</form>
</div>
</div>
</body>
</html>
3.Service
前面提到过,Service是一些公用的数据和方法的封装,可以用在不同的controller中。AngularJS可以使用依赖注入的方法将这些定义的service注入到相应的controller中,便可以使用service中的数据和方法。
4.Directive
directive是angularjs的一大亮点。AngularJS自己有一些内置指令如ng-click、ng-if等,用户也可以自己定义指令,如这里的story。
此篇旨在大致的了解了AngularJS的过人之处,如何构建项目,每个部分的作用。
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。
友情赞助
如果你觉得博主的文章对你那么一点小帮助,恰巧你又有想打赏博主的小冲动,那么事不宜迟,赶紧扫一扫,小额地赞助下,攒个奶粉钱,也是让博主有动力继续努力,写出更好的文章^^。
1. 支付宝 2. 微信
AngularJS in Action读书笔记1——扫平一揽子专业术语的更多相关文章
- AngularJS in Action读书笔记6(实战篇)——bug hunting
这一系列文章感觉写的不好,思维跨度很大,原本是由于与<Angularjs in action>有种相见恨晚而激发要写点读后感之类的文章,但是在翻译或是阐述的时候还是会心有余而力不足,零零总 ...
- AngularJS in Action读书笔记4(实战篇)——创建Statistic模块
个人感觉<Angularjs in action>这本书写的很好,很流畅,循序渐进,深入浅出,关键是结合了一个托管于Github上的实例讲解的,有代码可查,对于初学者应该是个不错的途径.( ...
- AngularJS in Action读书笔记2——view和controller的那些事儿
今天我们来818<angularjs in action>的第三章controller和view. 1.Big Picture概览图 View是angularjs编译html后呈现出来的, ...
- AngularJS in Action读书笔记5(实战篇)——在directive中引入D3饼状图显示
前言: "宁肯像种子一样等待 也不愿像疲惫的陀螺 旋转得那样勉强" 这是前几天在查资料无意间看到的一位园友的签名,看完后又读了两遍,觉得很有味道.后来一寻根究底才知这是出资大诗 ...
- AngularJS in Action读书笔记3——走近Services
试着想想这些问题:如果一个controller只关心自己所控制的view页面,那么对于整个application来说,你如何调用想要的function:如果controller从来都不会和其他cont ...
- AngularJS高级程序设计读书笔记 -- 指令篇 之 内置指令
1. 内置指令(10-12 章) AngularJS 内置超过 50 个内置指令, 包括 数据绑定,表单验证,模板生成,时间处理 和 HTML 操作. 指令暴露了 AngularJS 的核心功能, 如 ...
- AngularJS高级程序设计读书笔记 -- 大纲篇
零. 初衷 现在 AngularJS 4 已经发布了, 楼主还停留在 1.x 的阶段, 深感自卑. 学习 AngularJS 的初衷是因为, 去年楼主开始尝试使用 Flask 开发自动化程序, 需要用 ...
- AngularJS高级程序设计读书笔记 -- 服务篇
服务是提供在整个应用程序中所使用的任何功能的单例对象. 单例 : 只用一个对象实例会被 AngularJS 创建出来, 并被程序需要服务的各个不同部分所共享. 1. 内置服务 一些关键方法也被 Ang ...
- AngularJS高级程序设计读书笔记 -- 过滤器篇
一. 过滤器基础 过滤器用于在视图中格式化展现给用户的数据. 一旦定义过滤器之后, 就可在整个模块中全面应用, 也就意味着可以用来保证跨多个控制器和视图之间的数据展示的一致性. 过滤器将数据在被指令处 ...
随机推荐
- CSharpGL(40)一种极其简单的半透明渲染方法
CSharpGL(40)一种极其简单的半透明渲染方法 开始 这里介绍一个实现半透明渲染效果的方法.此方法极其简单,不拖累渲染速度,但是不能适用所有的情况. 如下图所示,可以让包围盒显示为半透明效果. ...
- C#函数式编程之可选值
在我们的实际开发中已经会遇到可空类型,而在C#中自从2.0之后就提供了可空类型(Nullable<T>),普通的值类型是不可以赋值为NULL,但是在类型的后面加上问号就变成了可空类型,这样 ...
- 使用ASP.NET Web API 2创建OData v4 终结点
开放数据协议(Open Data Protocol[简称OData])是用于Web的数据访问协议.OData提供了一种对数据集进行CRUD操作(Create,Read,Update,Delete)的统 ...
- Asp.net下使用HttpModule模拟Filter,实现权限控制
在asp.net中,我们为了防止用户直接从Url中访问指定的页面而绕过登录验证,需要给每个页面加上验证,或者是在模板页中加上验证.如果说项目比较大的话,添加验证是一件令人抓狂的事情,本次,我就跟大家分 ...
- Java多线程系列--“JUC锁”07之 LockSupport
概述 本章介绍JUC(java.util.concurrent)包中的LockSupport.内容包括:LockSupport介绍LockSupport函数列表LockSupport参考代码(基于JD ...
- Perl重命名当前目录下的文件
下载的zip包解压后,中文都变成了乱码,就写了个脚本重命名文件. use strict; use warnings; use Cwd; sub main { my $dir = getcwd(); o ...
- AngularJS快速入门指南12:模块
AngularJS模块定义了一个application. 模块是一个application中不同部分的容器. application中的所有控制器都应该属于一个模块. 带有一个控制器的模块 下面这个a ...
- Git学习笔记(4)——添加远程仓库,克隆远程库,以及库的推送
本文记录了远程库的连接和库的克隆和推送. 远程仓库简介 Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上.有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且 ...
- java内功 ---- jvm虚拟机原理总结,侧重于虚拟机类加载执行系统
参考书籍:<深入理解java虚拟机>,三天时间用了八个小时看完,像读一本武侠小说,挺爽. 另外需声明:图片都是从我自己的csdn博客转载,所以虽然有csdn标识,但都是我自己画的图片. j ...
- Java处理Radius access-challenge
最近使用 RSA Authentication Manager, 并且与其自带的Radius server整合, RSA的Radius server 配置不太透明, 目前只配成功了PAP方式的验证,C ...