angular2系列教程(五)Structural directives、再谈组件生命周期
今天,我们要讲的是structural directives和组件生命周期这两个知识点。structural directives顾名思义就是改变dom结构的指令。著名的内建结构指令有 ngIf, ngSwitch and ngFor。
例子
例子是我自己改写的,编写一个structural directives,然后通过这个指令实例化和注销组件,在此同时监视组件生命周期。
UnlessDirective
这个指令是官网示例中的指令。
app/unless.directive.ts
import {Directive, Input} from 'angular2/core'; import {TemplateRef, ViewContainerRef} from 'angular2/core'; @Directive({ selector: '[myUnless]' }) export class UnlessDirective { constructor( private _templateRef: TemplateRef, private _viewContainer: ViewContainerRef ) { } @Input() set myUnless(condition: boolean) { if (!condition) { this._viewContainer.createEmbeddedView(this._templateRef); } else { this._viewContainer.clear(); } } }
通过注入TemplateRef, ViewContainerRef这两个服务,来控制template的实例化和注销。TemplateRef可以让我们获取指令所在的元素的template,ViewContainerRef提供了多种视图容器的方法。
更详细的介绍:
用于测试的组件
接下来我们编写一个用于测试的组件。
app/lifecycle.ts
import {Component,Input} from 'angular2/core'; import {bootstrap} from 'angular2/platform/browser'; import {OnChanges, SimpleChange,OnInit,AfterContentInit,AfterContentChecked,AfterViewInit,AfterViewChecked,OnDestroy} from 'angular2/core'; @Component({ selector: "lifecycle", template: ` <div> <span>{{name}}</span> <button (click)="doSomething()">click and watch the lifecycle</button> </div> ` }) export class Lifecycle implements OnChanges, OnInit,AfterContentInit,AfterContentChecked,AfterViewInit, AfterViewChecked, OnDestroy{ @Input() name:string doSomething(){ console.log('***********doSomething**********'); setTimeout(()=>{ console.log('***********setTimeout**********'); this.name='susan' },1000) } ngOnInit(){console.log('onInit');} ngOnDestroy(){console.log('OnDestroy')} ngOnChanges(changes: {[propertyName: string]: SimpleChange}){console.log('ngOnChanges',changes)} ngAfterContentInit(){console.log('AfterContentInit')} ngAfterContentChecked(){console.log('AfterContentChecked')} ngAfterViewInit(){console.log('AfterViewInit')} ngAfterViewChecked(){console.log('AfterViewChecked')} }
这段代码我们做了这些事:
- 渲染一个span一个button
- 设置成员变量name,@input代表从parent输入
- 设置成员函数doSomething,打印一个信息,执行一个异步操作setTimeout
- 继承接口,设置所有的生命周期钩子,并打印信息
我们将使用这个组件,来监视组件生命周期。
使用指令控制组件
我们将我们的组件渲染出来,并用我们编写的结构指令“myunless”去实例化和注销这个组件
app/app.ts
import {Component} from 'angular2/core'; import {bootstrap} from 'angular2/platform/browser'; import {UnlessDirective}from './unless.directive'; import {Lifecycle} from './lifecycle' @Component({ selector: "app", directives:[UnlessDirective,Lifecycle], template: ` <button (click)="condition = !condition" [style.background] = "condition ? 'orangered': 'lightgreen'" > Set 'condition' to {{condition ? 'False': 'True'}} </button> <lifecycle *myUnless="condition" name="lewis"></lifecycle> ` }) export class App { constructor() {} } bootstrap(App, []) .catch(err => console.error(err));
这段代码我们干了这些事:
- 注入组件和指令directives:[UnlessDirective,Lifecycle]
- 渲染一个button控制成员变量condition的正负
- 渲染我们的组件lifecycle,并使用指令控制它的实例化和注销<lifecycle *myUnless="condition" name="lewis"></lifecycle>
- 最后启动这个app组件bootstrap(App, []) .catch(err => console.error(err));
开始测试
刷新页面:
- onInit是在组件第一次ngOnChanges时执行
- OnChanges在input和output绑定的值变化时候;我们可以看到打印了变化的值。可以替代ng1中的$watch;
- AfterContentInit、AfterViewInit分别代表在组件内容和视图初始化后执行。
- AfterContentChecked和AfterViewChecked是在组件内容和视图检查完后执行。
这里没有DoCheck,因为接口没有证实。
点击Set 'condition' toTrue按钮,页面上的组件被注销
console打印:
点击Set 'condition' to False按钮,页面上的组件重新被实例化:
console打印:
打印了一次Onchanges、onInit、AfterContentInit、AfterViewInit、AfterContentChecked和AfterViewChecked,说明组件实例化,只需要触发一轮初始化和变化检查。与刷新页面的五次对比,我们可以知道多余的“变化检查”,可能来源于angualr的启动。
点击click and watch the lifecycle按钮,一秒后页面上的name变为susan:
console打印
先打印一次AfterContentChecked和AfterViewChecked,一秒后又打印两次。OnChanges没有触发。
结论和收获
- TemplateRef, ViewContainerRef这两个服务可以帮助我们实现结构指令的编写
- 结构指令可以完全注销组件,节约性能消耗
- 组件实例化,只需要触发一轮初始化和“变化检查”
- angualr的启动会触发多次“变化检查”
- 我们可以继承OnChanges接口,来实现类似ng1中的$watch功能,获取变化前后的值,但是只能监视@input装饰的变量
- ng2使用zone,将window对象上常见的异步方法(setTimeout等),都打上了“猴子补丁”,使其可以直接更新视图,我们再也不用在异步中写ng1中的$apply了
- 我们可以使用setTimeout(()=>{},0),在浏览器的一轮“event loop”后来触发ng2的“变化检查”
- 我们触发类的成员函数(doSomething)时,也会导致ng2的“变化检查”
教程源代码及目录
如果您觉得本博客教程帮到了您,就赏颗星吧!
https://github.com/lewis617/angular2-tutorial
angular2系列教程(五)Structural directives、再谈组件生命周期的更多相关文章
- Fastify 系列教程三 (验证、序列化和生命周期)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) 验证 Fast ...
- angular2系列教程(十)两种启动方法、两个路由服务、引用类型和单例模式的妙用
今天我们要讲的是ng2的路由系统. 例子
- CRL快速开发框架系列教程五(使用缓存)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- C#微信公众号开发系列教程五(接收事件推送与消息排重)
微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...
- NGUI系列教程五(角色信息跟随)
在一些网络游戏中,我们常常可以看到角色的上方显示着角色的名称,等级,血量等信息.它们可以跟随角色移动,并且可以显示和隐藏.今天我们就来学习一下这些功能的实现方法.1. 新建unity工 程,导入NGU ...
- angular2系列教程(一)hello world
今天我们要讲的是angular2系列教程的第一篇,主要是学习angular2的运行,以及感受angular2的components以及模板语法. 例子 这个例子非常简单,是个双向数据绑定.我使用了官网 ...
- Android Studio系列教程五--Gradle命令详解与导入第三方包
Android Studio系列教程五--Gradle命令详解与导入第三方包 2015 年 01 月 05 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://s ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(五) Data Access Application Block
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(五) Data Access Application Block 企业库数据库访问模块通过抽象工厂模式,允许用户 ...
- Android系列之Fragment(二)----Fragment的生命周期和返回栈
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
随机推荐
- NodeJs之调试
关于调试 当我们只专注于前端的时候,我们习惯性F12,这会给我们带来安全与舒心的感觉. 但是当我们使用NodeJs来开发后台的时候,我想噩梦来了. 但是也别泰国担心,NodeJs的调试是很不方便!这是 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(66)-MVC WebApi 用户验证 (2)
系列目录 前言: 回顾上一节,我们利用webapi简单的登录并进行了同域访问与跨域访问来获得Token,您可以跳转到上一节下载代码来一起动手. 继续上一篇的文章,我们接下来演示利用拿到的Token来访 ...
- iOS开发--ChildViewController实现订单页的切换
先不说废话, 上效果图, 代码量也不大, 也不上传github骗星星了, 你们复制粘贴下代码, 就可以轻而易举的弄出一个小demo. 这个代码的实现并不复杂, 甚至于说非常简单, 就是逻辑有点小绕, ...
- 分享一个MySQL分库分表备份脚本(原)
分享一个MySQL分库备份脚本(原) 开发思路: 1.路径:规定备份到什么位置,把路径(先判断是否存在,不存在创建一个目录)先定义好,我的路径:/mysql/backup,每个备份用压缩提升效率,带上 ...
- 我的MYSQL学习心得(六) 函数
我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
- 【Knockout.js 学习体验之旅】(1)ko初体验
前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...
- iOS开发系列--App扩展开发
概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...
- EasyPR--开发详解(4)形态学操作、尺寸验证、旋转等操作
在上一篇深度分析与调优讨论中,我们介绍了高斯模糊,灰度化和Sobel算子.在本文中,会分析剩余的定位步骤. 根据前文的内容,车牌定位的功能还剩下如下的步骤,见下图中未涂灰的部分. 图1 车牌定位步骤 ...
- 如果你发现mysql的外键约束不管用了
不知为何我机子上的mysql竟然默认关闭外键约束,导致我试了好多遍都可以插入非法值,以下语句可以开启约束 SET foreign_key_checks = 1; (0则关闭) 备忘
- 为革命保护视力 --- 给 Visual Studio 换颜色
“为革命,保护视力,预防近视,眼保健操开始......” 这个应该是最老版本的眼保健操了,你听过? 一堆废话 且不说上面这个眼保健操到底有木有用,让眼睛放松下还是很有必要的,尤其是现在天天对着不是手机 ...