一.结构型指令
1.*的作用
-
*ngIf / *ngFor
是Angular的指令,*
是一个语法糖,避免复杂写ng-template<a *ngIf="user.login">退出</a>
等同于
<ng-template [ngIf]="user.login"> <a>退出</a> </ng-template>
2.Angular Dom操作
-
ViewContainerRef和ElementRef对比
<!-- 如果想在icon元素同级下面创建一个button元素的子节点,此时button就是ViewContainer,即要在哪个容器里面创建,ElementRef相当于表示button节点,想修改节点属性则用ElementRef,在节点内容创建子视图则使用ViewContainerRef --> <button class="fab-button"> <icon>add</icon> </button>
-
ViewContainerRef和TamplateRef
- TemplateRef:用于表示内嵌的 template 模板元素,通过 TemplateRef 实例,我们可以方便创建内嵌视图(Embedded Views),且可以轻松地访问到通过 ElementRef 封装后的 nativeElement。需要注意的是组件视图中的 template 模板元素,经过渲染后会被替换成 comment 元素。
- ViewContainerRef:用于表示一个视图容器,可添加一个或多个视图。通过 ViewContainerRef 实例,我们可以基于 TemplateRef 实例创建内嵌视图,并能指定内嵌视图的插入位置,也可以方便对视图容器中已有的视图进行管理。简而言之,ViewContainerRef 的主要作用是创建和管理内嵌视图或组件视图。
-
ViewRef 与 EmbeddedViewRef 之间有什么关系
- ViewRef 用于表示 Angular View(视图),视图是可视化的 UI 界面。
- EmbeddedViewRef 继承于 ViewRef,用于表示
<template>
模板元素中定义的 UI 元素。
-
@ViewChild返回的是一个引用
-
实例代码
@Component({ selector: 'sample', template: ` <span #test>Test span</span> ` }) export class SampleComponent implements AfterViewInit { @ViewChild("test", {read: ElementRef}) tref: ElementRef; ngAfterViewInit(): void { console.log(this.tref.nativeElement.textContent);//Test span } }
-
ViewChild装饰器的基本语法
@ViewChild([reference from template], {read: [reference type]});
-
简单的html,如span,返回的类型是ElementRef;template模板,返回的类型是TemplateRef
-
-
ElementRef
-
它只包含与之关联的原生元素(native element)[其实就是只能看nativeElement内容(DOM)]
-
ElementRef可以获取内部的DOM元素内容,还可以通过依赖注入的方式获取当前组件的DOM元素
@Component({ selector: 'sample', template: ` <span #test>Test span</span> ` }) export class SampleComponent implements AfterViewInit { constructor(private hostElement: ElementRef) { console.log(this.hostElement.nativeElement); //输出<span #test>Test span</span>,即当前组件的DOM树 } }
-
-
ViewRef
-
ViewRef 表示一个Angular 视图。在 Angular 框架中,视图(View)是应用程序UI的基本构件。
-
Angular 支持两种视图
- Embedded Views which are linked to a Template (连接到模板的嵌入视图)
- Host Views which are linked to a Component (连接到组件的宿主视图)
-
创建嵌入视图
-
模板仅包含视图的蓝图。可以使用前面提到的 createEmbeddedView 方法从模板中实例化一个视图[需要进行实例化再使用]
ngAfterViewInit() { let view = this.test.createEmbeddedView(null); }
-
-
创建宿主视图
-
当组件被动态实例化时,会创建宿主视图。使用 ComponentFactoryResolver 可以动态地创建一个组件
constructor(private injector: Injector, private r: ComponentFactoryResolver) { let factory = this.r.resolveComponentFactory(ColorComponent); let componentRef = factory.create(injector); let view = componentRef.hostView; }
-
在 Angular 中,每个组件都被绑定到一个注入器(injector)的特定实例,因此我们在创建组件时传递当前的注入器实例。另外,不要忘记必须将动态实例化的组件添加到模块或托管组件的 EntryComponents中。因此,我们已经看到了如何创建嵌入式视图和宿主视图。一旦创建了视图,就可以使用 ViewContainer将其插入到DOM中。
-
-
-
ViewContainerRef
-
ViewContainerRef表示一个容器,其中可以附加一个或多个视图,任何DOM元素都可以用作视图容器
-
ViewContainer 为操作视图提供了一个方便的API
class ViewContainerRef { ... clear() : void insert(viewRef: ViewRef, index?: number) : ViewRef get(index: number) : ViewRef indexOf(viewRef: ViewRef) : number detach(index?: number) : ViewRef move(viewRef: ViewRef, currentIndex: number) : ViewRef element: ElementRef length: number createComponent(componentFactory...): ComponentRef<C> createEmbeddedView(templateRef...): EmbeddedViewRef<C> }
-
插入视图:一旦我们有了视图,我们就可以使用insert方法将它 insert 到DOM中。接下来的示例表示从模板创建一个嵌入式视图,并将其插入标记的特定位置
html: <ng-container #test>Test</ng-container> <ng-template #templatetest> <span>hahaha</span> </ng-template> ts: @ViewChild('test', {read: ViewContainerRef}) test: ViewContainerRef; @ViewChild('templatetest') templatetest: TemplateRef<any>; ngAfterViewInit(): void { let view = this.templatetest.createEmbeddedView(null); console.log(this.test); console.log(this.templatetest); this.test.insert(view); }
-
删除视图:从DOM中删除一个视图,我们可以使用 detach方法。所有其他方法都是自解释性的,可用于获取索引视图的引用,将视图移到另一个位置,或者从容器中删除所有视图
-
创建视图:可以使用createComponent()方法或createEmbeddedView()方法进行创建
-
-
ngTemplateOutlet和ngComponentOutlet
-
ngTemplateOutlet
-
它将DOM元素标记为 ViewContainer ,并在其中插入一个由模板创建的嵌入视图,而不需要在组件类中显式地这样做。这意味着上面的例子中我们创建了一个视图并将其插入#vc DOM元素,可以这样重写,我们在组件类中不使用任何实例化代码的视图。
@Component({ selector: 'sample', template: ` <span>I am first span</span> <ng-container [ngTemplateOutlet]="tpl"></ng-container> <span>I am last span</span> <template #tpl> <span>I am span in template</span> </template> ` }) export class SampleComponent {}
-
-
ngComponentOutlet
-
该指令类似于 ngTemplateOutlet,其不同之处在于它创建了一个宿主视图(实例化一个组件),而不是一个嵌入式视图。你可以这样使用
<ng-container *ngComponentOutlet="colorComponent"></ng-container> <!-- colorComponent需要在ts中指明类型如colorComponent=ColorComponent -->
-
-
-
您可以通过使用 ViewChild 查询和模板变量引用来获得 Angular DOM 抽象的引用。围绕DOM元素的最简单的包装是 ElementRef 。对于模板,您有 TemplateRef,它允许您创建一个嵌入式视图。 可以通过使用 ComponentFactoryResolver创建的 componentRef 访问宿主视图。视图可以使用 ViewContainerRef 进行操作。有两种指令使手动过程变为自动化:ngTemplateOutlet ——操作嵌入视图 和ngComponentOutlet—— 创建宿主视图(动态组件)
二.模块
1.什么是模块?
-
模块相当于一组具有相同功能的文件的集合,模块将这些文件组织起来
-
模块的元数据
imports: [] declarations: []//当前module内部的组件都需要declarations定义 entryComponents: [] //表示进来模块的时候就会加载的,而不是调用的时候才去加载,不是显示的表现出来,而是通过某种机制触发的 exports:[] //如果当前模块的组件希望大家公用的,需要进行export出来,否则别人没法使用
-
forRoot(),forChild()是什么?
-
点进源文件看的话,其实是两个静态方法(两个工厂)
-
实例代码
@NgModule() export class ServicesModule { //我们常会遇到一种情况,源数据(NgModule里内容)根据不同情况去变化的 //不能写不同的怎么办? //不写NgModule的定义,返回的工厂方法里定义Module static forRoot():ModuleWithProviders { return { ngModule: ServicesModule, providers: [] } } } //其他文件导入的时候应使用 ServicesModule.forRoot()进行导入
-
2.ngClass、ngStyle、[class.yourstyle]
-
ngClass用于条件动态指定样式类,适合对样式做大量更改的情况。给出字典的对象,key为class值,value为true或false表示样式class是否应用
-
ngStyle用于条件动态指定样式,适合少量更改的情况
-
[class.yourcondition]="condition"直接对应一个条件
-
实例代码
<!-- ngClass --> <div [ngClass]="{'completed':item.completed}">completetd是class样式名</div> <!-- ngStyle --> <div [ngStyle]="{'order':list.order}"></div><!--可以利用order属性实现flex容器的排序,从而实现拖拽元素的位置--> <!-- [class.yourcondition] --> <div [class.completed]="item.completed">completetd是class样式名</div>