Angular结构型指令、模块和样式

一.结构型指令

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>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值