AngularJS1.x 部件

AngularJS1.x 数据绑定过程 — $watch, $apply, $digest

笔记参考于翻译:理解$watch ,$apply 和 $digest —- 理解数据绑定过程

英语原文:Watch how the apply runs a digest

浏览器事件循环和Angular.js扩展

​ 我们的浏览器一直等待,比如用户交互。假如你点击一个按键或者在输入框里输入东西,事件的回调函数就会在javascript解释器里执行,然后你就可以做任何DOM操作,等回调函数执行完毕时,浏览器就会相应地对DOM做出变化。Angular拓展了这个事件循环,生成一个有时称为angular context的执行环境。

记住angualr context这个重要的概念。其联系到接下来说的$apply$digest$watch 的使用。

1.$watch队列 ($watch list)

​ 每次你绑定一些东西到那你的UI上时,你就会往 $watch 队列里插入一条$watch。想象一下$watch就是那个可以检测它所监视的model里有变化的时候的东西。

只有绑定到UI后,才会生成一个$watch

  • $watch的生成时间: 当我们的模板加载完成时,也就是在linking简短(Angular分为compile阶段和linking阶段),Angular解释器会寻找每个directvie, 然后生成每个需要的$watch

2. $digest 循环

​ 当浏览器接收到可以被angualr context 处理的事件时,$digest循环就会触发。

​ 这个循环是由两个更小的循环组合起来的。一个处理evalAsync队列,另一个处理$watch队列。$digest队列将会遍历我们的$watch,并且对$watch一个个进行询问检查$watch是否有更新过,这就是所谓的dirty-checking。如果其中至少有一个$watch更新过,那这个循环将会再次触发,直到所有的$watch都没有变化。这样就能保证每个model都已经不再变换。

如果在处理$watch时, `$digest循环超过10次,那它将会抛出一个异常,防止无限循环。

​ 当$digest循环结束时,DOM会相应地变化。

3. 通过$apply来进入angualr context

$apply 决定事件是否进入angualr context

​ 当事件触发时,如果你调用$apply,则该事件会进入angular context,如果没有调用则不会进入。

  • 什么时候Angualr不会自动为我们调用$apply

Controller directive model使用情况:

笔记参考于:AngularJS:何时应该使用Directive、Controller、Service?

通过scope来维护数据时非常粗暴的一种方式,由于其它controller directive model 的英系那个,scope很容易就会崩溃或者变脏。它很快就会变成一团乱麻。
通过一种集中的途径(在这里,就是service)来管理所有数据,然后通过某种方式来请求修改它,这样不仅仅会更加清晰,同时当应用的体积不断增大的同时也更容易管理。
最后,它还可以让我们的代码模块化(这也是Angular很擅长的一件事情)。一旦我们在其它项目中需要用到这个service,我们没有必要在scope controller filter等等东西里面到处去查找相关的代码,因为所用东西都在service里面。

service使用情形:无论何时,当我们需要在不同的域中共享数据的时候,我们需要使用service。另外,多亏了Angualr的依赖注入系统,实现这一点是很容易的。

controller使用情形:controller应该纯粹地用力把service,依赖关系以及其它对象串联到一起,然后通过scope把它们关联到view上。
如果在我们的视图里面需要处理复杂的业务逻辑,那么把它们放到controller里面也是一个非常不错的选择。

directive使用情形:在我们编写的大量AngularJS应用中,应用中最主要的复杂部分都在directive中,它被用来操作和修改DOM。

Angular JS 之 Factory VS Service VS Provider

笔记参考: AngularJS 之 Factory vs Service vs Provider

英语原文:[AngularJS: Factory vs Service vs Provider]https://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/)

​ Angular 应用里大部分的业务逻辑和持久化数据都应该放在service里。

​ Controller 不应该用来保存持久化数据。出于内存性能的考虑,controller只在需要的时候才会初始化,一旦不需要就会被抛弃。因此,每次当你切换或刷新页面的时候,Angular 就会清空当前的controller。与此同时,service可以用来永久保存应用的数据,并且这些数据可以在不同的controller之间使用。

​ Angular 提供了3种方法创建并注册我们自己的service。

  • Factory
  • Service
  • Provider
简而言之:
  1. 用Factory就是创建一个对象,为它添加属性,然后把这个对象返回出来。你把service传进controller之后,在controller里这个对象的属性就可以通过factory使用了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    app.controller('myFactoryCtrl', function ($scope, myFactory) {
    $scope.artist = myFactory.getArtist()
    })

    app.factory('myFactory', function () {
    var _artist = '';
    var service = {}

    service.getArtist = function () {
    return _artist
    }

    return service;
    })
  2. Service 是用new关键字实例化的。因此,你应该给this添加属性,然后service返回 this。你把service传进controller之后,在controller里 this 上的属性就可以通过 service 来使用了。

Javascript中 new 关键字具体怎么工作的,见下文。。。

1
2
3
4
5
6
7
8
9
10
app.controller('myServiceCtrl', function ($scope, myService) {
$scope.artist = myService.getArtist();
});

app.service('myService', function () {
var _artist = '';
this.getArtist = function () {
return _artist;
}
});
  1. Providers是唯一一种你可以传进 .config() 函数的service。当你想要在service对象启用之前,先进行模块范围的配置,那就应该用provider。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
app.controller('myProviderCtrl', function ($scope, myProvider) {
$scope.artist = myProvider.getArtist();
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});

app.provider('myProvider', function () {
this._artist = '';
this.thingFromConfig = '';

//Only the properties on the object returned from $get are available in the controller.
this.$get = function () {
var that = this;
return {
getArtist: function () {
return that._artist;
},
thingonConfig: that.thingFromConfig
}
}
});

app.config(function (myProviderProvider) {
myProviderProvider.thingFromConfig = 'This was set in config()';
})
详细的比较:

暂时未补充。。。