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. 微信
相关文章
- [React] Write a Custom State Hook in React
- [Angular] Use Angular components in AngularJS applications with Angular Elements
- [Python] for.. not in.. Remove Deduplication
- [AngularJS] Interpolation fail in IE 11
- [AngularJS] New in Angular 1.5 ng-animate-swap
- [AngularJS] New bindToController in AngularJS 1.4
- [AngularJS] New in Angular 1.3 - Performance Boost with debugInfoEnabled
- [AngularJS] Accessing Data in HTML -- controllerAs, using promises
- [AngularJS] Promises in controller. 1. $q.defer(), defer.resolve(), defer.reject(), promise.then().then()
- [Svelte 3] Use an onMount lifecycle method to fetch and render data in Svelte 3
- [Functional Programming] Pull Many Random Numbers in a Single State ADT Transaction
- [AngularJS] Isolate State Mutations in Angular Components
- [AngularJS] 'require' prop in Directive or Component
- [AngularJS] Enable Animations Explicitly For A Performance Boost In AngularJS
- [AngularJS] New in Angular 1.3 - bindToController
- [AngularJS] Using ngModel in Custom Directives
- [AngularJS] Using Services in Angular Directives
- [AngularJS] Accessing Data in HTML -- controllerAs, using promises
- [AngularJS] Angular 1.3 $submitted for Form in Angular
- createBindingContext in SAP UI5
- dateFormat in DatePicker control Fiori - language 语言
- 试图添加产品到 Spartacus 购物车时遇到错误消息 - This item was already in your cart
- atitit.线程死锁 卡住无反应 的原因in cmd调用的解决方案 v3 q39
- atitit.javascript调用java in swt attilax 总结
- 成功解决Future Warning: The sklearn.neighbors.dist_metrics module is deprecated in version 0.22 and wil
- 成功解决SyntaxError: (unicode error) ‘unicodeescape‘ codec can‘t decode bytes in position 0-1: malformed
- 成功解决 File "h5pyh5t.pxd", line 14, in init h5py._conv (D:Buildh5pyh5py-2.7.0h5py_conv.c:7539)
- 已解决_tkinter.TcLError: couldn’t recognize data in image file “Image/nakamuraan.gif”
- AngularJS in Action读书笔记3——走近Services
- 【无标题】Non-parametric test for difference in mean