数据双向绑定并不是Angular最出彩的地方。大部分对AngularJs的介绍都偏重于使用,使用的学习只是学了AngularJs的API,而那只能AngularJs的很小一部分。随着使用越来越深,系统越来越大,我们也越来越迷失,是时候深入AngularJs的实现来学习。因为AngularJs 2.0就要来了,由于2.0和1不兼容,基于API的学习不再有用,而内部实现的精华才能延续。其实,软件的很多技术也大都如此,冲走的是实现,留下的是思想。

原文

深入探索AngularJS

作用域Scope是DOM和Directives交互的抽象

Scope是POJO对象

AngularJS只是往Scope中添加了很多“内部"属性,大部分以$开头,还有些以$$开头,两个$开头的属性一般不要使用。

Scope是上下文

应该看作是一个容器,保存着当前的上下文和上下文敏感的变量数据等

Scope继承树

  • Scope总是和一个DOM元素联系起来
  • Controller会创建一个新的Scope
  • Directive有时候会创建一个新的Scope
  • 其他情况会直接使用父级的Scope
  • 如果不在ng-app内,没有任何相关的Scope

Scope附加功能

AngularJS往Scope中添加了一些属性

遍历功能

  • $id

    Scope的唯一id号
  • $root
  • $parent
  • $$childHead
  • $$childTail
  • $$prevSibling
  • $$nextSibling

正交功能

Element和Attribute

Directive可以定义为Element(标识)也可以定义为标识的属性。 更为强大的架构就是综合应用这两种功能,用属性定义来改变或增强原Element的功能。

模块模式 - Module Pattern

模块模式是一个设计模式,它能够消除大量重复的 thisprototype使用。 Angular Material就使用这个模式开发模块代码 Angular Material Coding Conventions and Guidelines

参考: http://toddmotto.com/mastering-the-module-pattern/

创建模块

(function(){
//code
})();

这里申明了一个函数,然后马上调用它自己,这也被称作立即执行函数表达式 (Immediately-Invoked Function Expression)。这个函数就创建了一个新的作用域(Scope),从而模拟了类似私有域的效果, 把大部分代码从全局作用域(Gloable Scope)中隔离出来。

创建新的作用域之后,我们需要把代码赋于命名空间。

var Module = ( function () {
//code
})();

这样,我们就在全局作用域中申明了 Module,这样我们就可以任意调用它,甚至把它传给另外一个模块。

私有方法 - Private Method

Javascript所有的函数定义默认下都是全局的,而且Javascript也没有命名空间的概念,这两个缺陷使得Javascript很容易产生名称冲突。 模块模式可以帮助解决这些问题。

Javascript 本身不能够定义私有方法,但是我们可以使用模块模式模拟出私有方法的效果。

私有方法本质上是:你不希望外部用户调用执行的某个作用域内部的任何东西。特别是那些从服务器读取或回写的操作。

通过模块模式,我们可以如下隐藏私有方法:

var Module = (function(){
var privateMethod = function(){
//do something
};
})();

在新作用域内部申明的方法privateMethod就很好的隐藏起来,任何外部试图调用privateMethod都会导致错误。

理解返回 - Return

景点模块模式可以用 return返回一个对象给模块,那些在该对象下声明的方法可以通过模块的命名空间来调用。

var Module = (function(){
return {
publicMethod:function(){
//code
}
};
})();

调用: Module.publicMethod();

这和标准方式定义的对象没有任何区别:

var myObj = {
defaults: { name: 'Hao Wang'},
publicMethod: function () {
console.log(this.defaults);
}
}; //调用
myObj.publicMethod();

当时标准方式的问题是,一些内部属性和方法都暴露出来了,不能隐藏(Javascript没有私有属性和方法)。 如上面例子中的defaults就有可能被外部用户修改,导致不期望的行为。

Promise - 异步的承诺

Promise让异步调用看起来更像同步调用,从而很容易的取到返回值和捕获异常。

介绍

使用Promise我们可以在任何一个执行点捕获错误,然后忽略剩下的执行步骤。 这种流程控制来源于新的代码风格本身,无需额外的代码。 从而,我们可以很容易的组合多个函数功能并且异常以冒泡式的抛出,同时有维持异步运行的能力。

Promise自始自终都是异步运行,我们不用担心它会阻塞其它部分的代码运行。

Promise in Angular

Angular的事件循环(Event Loop)在$rootScope.$evalAsync阶段解析(Resolve)Promise,直到$digest运行循环结束。 我们和容易的把Promise的结果输出成视图,这能够直接把XHR调用的结果直接赋给$scope对象的一个属性。

使用Promise到后台取数据的一个实例

<ul ng-controller="DashboardController">
<li ng-repeat="pr in pullRequests">
{{pr.title}}
</li>
</ul>

当用服务返回一个promise, 我们可以用.then()方法与promise进行交互操作, 我们可在该方法中修改scope中的任何变量,从而改变视图。

angular.module('myApp', [])
.controller('DashboardController', ['$scope', 'GithubService', function($scope, GithubService){
GithubService.getPullRequests(123) //这里返回的是Promise
.then(tunction(data){
$scope.pullRequests = data.data;
});
}]);

创建一个Promise

内建服务$q可以用来创建你自己的Promise。我们可以通过调用$q.defer()方法来创建一个“延迟”对象: var deferred = $q.defer();

“延迟”对象有三个方法和一个promise属性,该属性返回一个Promise对象。

  • .resolve(value) - 解析(返回结果)方法
  • .reject(reason) - 拒绝方法;等同于解析出一个拒绝对象.resolve($q.reject(reason));
  • .notify(value) - 返回执行的状态方法

Promise执行状态

如果我们有一个长时间运行的请求,可以调用.notify()来及时返回进程状态。 通常,我们会把这个长时间任务放在一个服务中:

.factory('GithubService', funcion($q, $http){
var getEventsFromRepo= function(){
//task
};
var service = {
makeMultipleRequests: function(repos){
for (var i=0; i < repos.length; i++) {
output.push(getEventsFromRepo(repos[i]));
percentComplete = (i+1) / repos.length * 100;
d.notify(percentComplete);
}
d.resolve(output);
return d.promise;
}
}
return service;
});

这里,每取一个repo, 我们就会收到一个进程状态的通知。下面是对这个Pomise的使用和状态通知的显示

.controller('HomeController', function($scope, GithubService){
GithubService.makeMultipleRequests(['auser/behavior','..'])
.then(function(result){
//Handle the result
}, function(err){
//Error occurred
}, function(percentComplete) {
$scope.progress=percentComplte;
});
});

异步流

Promise的then()方法返回一个新的Promise, 这个新的Promise实际上是在原始Promise的值解析之后创建的。这样我们就可以用then()让异步的执行通过一个一个Promise串联下去。

使用then()我们创建了异步执行体流,这样我们可以在任何一步切入,然后切换不同的返回值。 这种切换也可以染我们暂停或者延迟解析的流程。

$http服务就是使用这种切入来实现请求和响应的interceptors。

$q服务还有几个其他的帮助方法:

  • $q.all(promises) - 可以把多个Promise合并成一个Promise。
  • $q.defer() - 创建一个延迟对象。
  • $q.reject(reason) - 创建一个Promise,其解析值为rejection
  • $q.when(value) - 把一个对象封装成为Promise,这个对象可以是普通对象也可以原本就是Promise。

与服务器的交互

谈到后端时,我们有两种情况:有服务器后端和无服务器后端

ExpressJS作服务器后端

搭建Express

  1. 安装NodeJS
  2. 安装Express: $ npm install -g express-generator
  3. 创建网站: $ express myApp
  4. 运行App准备:` cd myApp && npm install -d
  5. 运行App: `$ node app.js
  6. 高级运行App (源代码的改动触发重新编译):

    $ npm install --save-dev node mon

    $ nodemon app.js

( 本文版权属于© 2015 卓逸天成 | 转载请注明作者和出处:卓逸知识文库 )

深入探索AngularJS(持续更新)的更多相关文章

  1. BLE资料应用笔记 -- 持续更新

    BLE资料应用笔记 -- 持续更新 BLE 应用笔记 小书匠 简而言之,蓝牙无处不在,易于使用,低耗能和低使用成本.'让我们'更深入地探索这些方面吧. 蓝牙无处不在-,您可以在几乎每一台电话.笔记本电 ...

  2. ( 译、持续更新 ) JavaScript 上分小技巧(三)

    最近家里杂事较多,自学时间实在少的可怜,所以都在空闲时间看看老外写的内容,学习之外顺便翻译分享~等学习的时间充足些再写写自己的一些学习内容和知识点分析(最近有在接触的:复习(C#,SQL).(学习)T ...

  3. ( 译、持续更新 ) JavaScript 上分小技巧(一)

    感谢好友破狼提供的这篇好文章,也感谢写这些知识点的作者们和将他们整理到一起的作者.这是github上的一篇文章,在这里本兽也就只做翻译,由于本兽英语水平和编程能力都不咋地,如有不好的地方也请多理解体谅 ...

  4. 【持续更新】JavaScript常见面试题整理

    [重点提前说]这篇博客里的问题涉及到了了JS中常见的的基础知识点,也是面试中常见的一些问题,建议初入职场的园友Mark收藏,本文会持续更新~ 1. 引入JS的三种方式 1.在HTML标签中直接使用,直 ...

  5. 中国.NET:各地微软技术俱乐部汇总(持续更新中...)

    中国.NET:各地微软技术俱乐部汇总(持续更新中...)   本文是转载文,源地址: https://www.cnblogs.com/panchun/p/JLBList.html by ​史记微软. ...

  6. BAT 前端开发面经 —— 吐血总结 前端相关片段整理——持续更新 前端基础精简总结 Web Storage You don't know js

    BAT 前端开发面经 —— 吐血总结   目录 1. Tencent 2. 阿里 3. 百度 更好阅读,请移步这里 聊之前 最近暑期实习招聘已经开始,个人目前参加了阿里的内推及腾讯和百度的实习生招聘, ...

  7. 前端深入之js篇丨Array数组操作从入门到成神Up Up Up,持续更新中

    写在前面 随着前端深入的不断学习,发现数组这个数据结构在前端中有着相当大的存在感,由于我初学前端的时候并没有系统性的学习数组,所以我将通过这篇文章同你一起学习数组,希望我们能一起进步,学会熟练操作数组 ...

  8. iPadOS 更新日志 - 持续更新中

    本文只是为了简单记录一下每个正式版本发布时间和更新内容,只有这个初衷,从2019年9月25日开始,将会持续更新. iPadOS 13.1 - 2019年9月25日 经全新命名的 iPadOS 是一款强 ...

  9. iOS面试高薪,进阶 你会这些呢嘛?(持续更新中)

    这个栏目将持续更新--请iOS的小伙伴关注!做这个的初心是希望能巩固自己的基础知识,当然也希望能帮助更多的开发者! 基础>分析>总结 面试 iOS常见基础面试题(附参考答案) iOS底层原 ...

随机推荐

  1. js判断是否安装pdf播放器

    function isPDFPluginInstall() { if (!isIE()) { //ie 浏览器 和 非ie浏览器支持 // not ie if (navigator.plugins & ...

  2. VC++ 在两个程序中 传递字符串等常量值的方法:使用了 WM_COPYDATA 消息的

    消息作用:    在进程间共享数据(内部通过创建内存映射文件) 消息介绍:需要用到的数据结构/类型:typedef struct tagCOPYDATASTRUCT {    ULONG_PTR dw ...

  3. Android菜鸟成长记6 -- 网络连接的检查

    在android开发中我们要经常考虑到各种问题.在开发android应用时,涉及到要进行网络访问,时常需要进行网络状态的检查,以提供给用户必要的提醒.一般可以通过ConnectivityManager ...

  4. scala 学习:object 和class, trait

    object: Scala中没有静态修饰符,static,在object下的成员全部都是静态的,如果在类中声明了与该类相同的名字的object则该object是该类的"半生对象", ...

  5. 客户端连接linux经常间隔性断开链接

    起因 在使用SecureCRT通过telnet或SSH访问linux时,总是出现过段时间操作就会断开连接提示重连的问题.起初以为是网络不稳定造成的,但我测试发现在服务器端一直可以ping通客户端IP, ...

  6. python学习笔记-Day6(1)

    shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式 >>> s=shelve.open('test') > ...

  7. 如何编译Less

    什么是LESS LESSCSS是一种动态样式语言,属于CSS预处理语言的一种.它编译后就是CSS了,大名鼎鼎的前端框架BootStrap就是用这个语言写的 下面示范下怎么用LESS编译成CSS,尽量简 ...

  8. IOS一些好的用户体验设置

    1,下载图片时,如果 用户操作UI,那么就停止子线程,用户停止操作子线程时,开启子线程继续下载. SDWebImage  :专门下载图片. 2,网络请求时.本地要进行一些验证,以减少服务器的压力.

  9. Odoo10 变化

    官方在 https://www.odoo.com/forum/help-1/question/fyi-what-has-odoo-r-d-been-working-on-lately-106945 发 ...

  10. Verilog之串口(UART)通信

    0:起始位,低电平:1~8:数据位:9:校验位,高电平:10:停止位,高电平. 波特率 “9600bps”表示每秒可以传输9600位. 波特率定时计数器由时钟频率除以波特率. 采集1~8位,忽略0.9 ...