浅析AngularJS中的生命周期和延迟处理

   这篇文章主要介绍了浅析AngularJS中的生命周期和延迟处理,是AngularJS中较为核心的深层次内容,需要的朋友可以参考下

  这里,我们再讨论一些常用的高级的控制反转容器(Inversion of Control containers):延迟加载(lazy-loading),生命周期管理(lifetime management),以及延迟的创建/处理(deferred creation/resolution)。

  延迟加载(Lazy-Loading)

  所谓延迟加载就是当你需要用到对象时候才对其进行实例化。许多依赖注入系统都会在一开始就创建组件,作为它的可依赖项目。不过有时候,直到在应用中用到它们之前,你都不会想去实例化这些组件。Angular 中,一个很好的例子就是,当你在配置的时候去设置一个行为,而该行为又会引用到一些还没创建的组件。

  假设你想拦截系统内建的 $log 服务,因此你把它存在了 $rootScope 里面。当然我不建议这样做,不过这样举例比较简单有效。为了拦截,你在配置的时候用到了 $provide 然后调用修饰方法。如果这时你想直接引用 $rootScope 的话,由于循环引用你会拿到个异常。而解决案是通过 $injector 延迟加载 $rootScope 。

  下面的代码只会在 $rootScope 第一次被使用的时候才去加载它。

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13

$provide.decorator(, [, ,
($delegate, $injector) {
log = $delegate.log.bind($delegate);
$delegate.log = (msg) {
rs = $injector.get();
(rs.logs === undefined) {
rs.logs = [];
}
rs.logs.push(msg);
log(msg);
};
$delegate;
}]);

  之后的调用都会拿到一样的单例 $rootScope。 这里有个可用例子。我之前好像听过有个(不对的)说法(Angular 只支持单例) … 当然不是真的。$injector 中的方法就是用来给你管理你的组件的生命周期的。

  生命周期管理

  生命周期涉及到你如何管理组件的实例。默认情况,当你注入一个 Angular 的依赖,依赖注入就会帮你创建它的一个副本然后在你的应用里面重用它。大多数情况下这确实是我们所期待的。而有些情况下,会要求同一组件的多个实例。假设下面的计数服务:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Counter($log) {
$log.log();
}
 
angular.extend(Counter.prototype, {
count: 0,
increment: () {
.count += 1;
.count;
}
});
 
Counter.$inject = [];
 
app.service(, Counter);

  你的应用要跟踪不同的计数器。而你注入该服务后,总会拿到一样的计数器。这难道是 Angular 的限制?

  当然不是。重复一次,通过 $injector 服务你可以在任何时候创建一个新副本。下面的代码用了两个独立的计数器:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13

app.run([, , ,
(rs, c, i) {
rs.count = c.count;
rs.update = c.increment;
rs.update2 = () {
c = i.instantiate(Counter);
rs.count2 = c.count;
rs.update2 = () {
c.increment();
rs.count2 = c.count;
};
};
}]);

  你可以看到计数器都是被独立的实例跟踪的,这里是可用例子。如果你需要经常生成新实例,你可以像这样注册服务:

  ?

1
2
3
4
5
6
7
8

app.factory(, [,
(i) {
{
getCounter: () {
i.instantiate(Counter);
}
};
}]);

  产生一个需要的实例就是那么简单,而且你可以用你的工厂组件来代替 $injector:

  ?

1
2
3
4
5
6
7
8
9
10
11

app.run([, ,
(rs, cf) {
c1 = cf.getCounter(),
c2 = cf.getCounter();
rs.count = c1.count;
rs.update = c1.increment;
rs.count2 = c2.count;
rs.update2 = () {
rs.count2 = c2.increment();
};
}]);

  你可以看看这个完整版本的可用例子。如你所见,用 Angular 的内建依赖注入是完全有可能管理你组件的生命周期的。那延迟处理(deferred resolution)又怎样呢 – 比如说,有些组件你需要在 Angular 已经配置好之后引入,而且需要用它们的依赖来包装起来。

  延迟处理(Deferred Resolution)

  我们已经介绍了在 Angular 中可以延迟处理依赖的一种方法。当你想包装某些东西的时候,你可以调用 $injector 服务的 instantiate ,然后它可以通过参数嗅探来解决依赖,看起来就像用 $inject 的静态属性一样,或者也可以通过检查你传给它的数组来实现的。也就是说,下面这个是完全有效写法:

  ?

1

$injector.instantiate(['dependency', Constructor]);

  你还可以调用带装饰数组的方法。假设你有一个方法依赖于 $log 服务,你可以运行时通过延迟处理来调用它,像下面这样:

  ?

1
2
3
4

myFunc = [, ($log) {
$log.log();
}];
$injector.invoke(myFunc);

  你可以看看这个可用例子(打开你的控制台,看看你按下按钮之后发生了什么)。

  总结

  综上所述,Angular 的依赖注入提供了许多高级特性,你在商业应用生产线上会希望并且经常会用到它们。factories, services, 和 providers 的便捷让 Angular 开发者常常产生错觉,认为这里只有唯一选项可用。而神奇之处在于 $injector 服务,你可以用它生成所需的单例,创建新的组件或者动态引用带依赖的方法。

  最后要注意的是,你客户端代码里面的注入即使在 Angular 之外也是可用的。我们来看一个在 Angular 之外包装的,通过注入调用 $log 服务的例子,点这里。为什么要把 ‘ng' 传入方法的数组?它是 Angular 的核心模块,当你包装你的模块的时候是会被隐式添加的,但是如果你的指令要生成自己的注入实例的时候,你就必须显式添加了。

时间: 2024-12-09 16:12:55

浅析AngularJS中的生命周期和延迟处理的相关文章

Java开发平台中的生命周期管理

对象的生命周期没有大家想的那么复杂.其实其就是回答了两个简单的问题.什么时候需要创建对象? 什么时候把对象消亡?这两个问题解决了,那么对象的生命周期问题也就解决了. 一.传统的对象生命周期管理方法. 为了对Java开发平台中的生命周期管理方法有一个更加深刻的理解,笔者认为大家需要对传统的生命 周期管理方法先有一个了解.因为这有助于大家有一个相互的对比,从而会对Java语言中的生命周期管理 方法会有一个比较直观的印象. 在传统的编程语言中,如C语言,其考虑对象的生命周期,主要是从对象与应用程序的执

深入浅析AngularJS中的module(模块)_AngularJS

什么是AngularJS的模块 我们所说的模块,是你的AngularJS应用程序的一个组成部分,它可以是一个Controller,也可以是一个Service服务,也可以是一个过滤器(Filter),也可以是一个directive(指令)等等-都是属于一个模块! 大多数的应用程序都是有一个自己的函数入口方法Main ,用它来进行初始化,以及加载装配各个模块,然后这些模块的组合,构成了你的应用程序,对吧? 但是,but, AngularJS应用程序却不是这样的哦,它没有main 方法,没有函数入口.

Android中Activity生命周期和启动模式详解_Android

Activity生命周期经典图解: 按键对生命周期的影响: BACK键: 当我们按BACK键时,我们这个应用程序将结束,这时候我们将先后调用onPause()->onStop()->onDestory()三个方法. 再次启动App时,会执行onCreate()->onStart()->onResume() HOME键: 当我们打开应用程序时,比如浏览器,我正在浏览NBA新闻,看到一半时,我突然想听歌,这时候我们会选择按HOME键,然后去打开音乐应用程序,而当我们按HOME的时候,A

实例讲解Android应用开发中Fragment生命周期的控制_Android

一.Fragment的生命周期初探 因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的. 如果Activity是暂停状态,其中所有的Fragment都是暂停状态:如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动:如果Activity被销毁,那么它其中的所有Fragment都会被销毁. 但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除F

Android中进程生命周期的优先级

学习Android最好的途径当然是强大的官方文档了,其中在Processes and Threads一节中对于进程生命周期淘汰优先级,有着详细的介绍.就不给大家转帖了,直接放译文吧,如下: Android系统会尽量维持进程的存在,但毕竟资源有限,当系统资源告急的时候会淘汰一部分进程.淘汰顺序的凭据就是系统进程的优先级了,优先级越高越不容易被杀死,反之亦然.系统总共为进程分了五个优先级,如下 一.前台进程(进程满足如下任一条件即为前台进程): 1. 拥有 一个执行了onresume方法正在与用户交

Android中Activity生命周期和启动模式详解

Activity生命周期经典图解: 按键对生命周期的影响: BACK键: 当我们按BACK键时,我们这个应用程序将结束,这时候我们将先后调用onPause()->onStop()->onDestory()三个方法. 再次启动App时,会执行onCreate()->onStart()->onResume() HOME键: 当我们打开应用程序时,比如浏览器,我正在浏览NBA新闻,看到一半时,我突然想听歌,这时候我们会选择按HOME键,然后去打开音乐应用程序,而当我们按HOME的时候,A

实例讲解Android应用开发中Fragment生命周期的控制

一.Fragment的生命周期初探 因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的. 如果Activity是暂停状态,其中所有的Fragment都是暂停状态:如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动:如果Activity被销毁,那么它其中的所有Fragment都会被销毁. 但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除F

浅析AngularJS中的指令_AngularJS

指令(Directives)是所有AngularJS应用最重要的部分.尽管AngularJS已经提供了非常丰富的指令,但还是经常需要创建应用特定的指令. 说到AngularJS,我们首先想到的大概也就是双向数据绑定和指令系统了,这两者也是AngularJS中最为吸引人的地方.双向数据绑定呢,感觉没什么好说的,那么今天我们就来简单的讨论下AngularJS这个框架的指令系统,本人也是初学,查阅了一些资料,要是有一些说的不好的地方,万望指出. 指令作为AngularJS中最为重要的部分,所以这个框架

Delphi2010中DataSnap高级技术(7)—TDSServerClass中Lifecycle生命周期三种属性说明

Lifecycle 三种属性: Session.Invocation.Server 这三种属性都用在什么情况,有什么要注意的事项,Delphi2010中罕有说明. 如果乱用这三种属性,你的服务程序有可能崩溃,数据混乱,内存占用大,效率低等问题! 下面我对这三种属性的使用环境逐一介绍: 1. Session 说明:这是delphi2010中默认属性,也是delphi推荐设置.Session会为每个来自客户端的链接,建立一个线程来实例化.实例化是什么概念呢?就是这个线程把所有你将要用到的类.函数等等