• angular 结构型指令If you’ve ever done any development with Angular (and I assume you have if you’ve made it here), it is inevitable that you have come across Structural directives. They’re super ...

    angular 结构型指令

    If you’ve ever done any development with Angular (and I assume you have if you’ve made it here), it is inevitable that you have come across Structural directives. They’re super easy to identify because they are all prefaced with a *; some of their greatest hits are NgIf, NgFor and NgSwitch, all of which are crucial to helping us as developers build lean, clean apps. But why the star? To understand Angular’s use of asterixes, we first need to understand what Structural directives actually do and then we can figure out what’s actually going on behind the scenes.

    如果您曾经使用Angular进行过任何开发(并且我假设您已经在这里完成了开发),那么不可避免地会遇到Structured指令。 它们非常容易识别,因为它们都以*开头。 NgIf,NgFor和NgSwitch是其中的佼佼者,当开发人员构建精简,干净的应用程序时,它们对帮助我们至关重要。 但是为什么是明星? 要了解Angular对星号的使用,我们首先需要了解Structured指令的实际作用,然后我们才能弄清楚幕后的实际情况。

    Within Angular, there are three main types of directives — structural, attribute and component. We’re going to largely ignore components as while they’re technically directives that manage a section of HTML based on their template, they do not quite fit into the scope of this blog.

    在Angular中,有三种主要类型的指令-结构,属性和组件。 我们将在很大程度上忽略组件,因为从技术上来说,组件是根据其模板管理HTML的一部分的指令,但它们并不完全适合本博客的范围。

    Attribute directives are used to change the element they are added to. Attribute directives, for the most part, appear to be normal HTML attributes. In the below example, we have used the Angular CLI to run ng g d exampleDirective (long form: ng generate directive exampleDirective) which has automatically created our exampleDirective.directive.ts and exampleDirective.directive.spec.ts files (in whatever directory you ran your command in) and has also automatically declared our new directive in our AppModule. This means that we are now free to use our directive like so:

    属性指令用于更改添加到它们的元素。 在大多数情况下,属性指令似乎是普通HTML属性。 在下面的示例中,我们使用Angular CLI运行ng gd exampleDirective (长格式:ng generate指令exampleDirective),它自动创建了exampleDirective.directive.ts和exampleDirective.directive.spec.ts文件(在您运行的任何目录中)您的命令),并且还自动在AppModule中声明了我们的新指令。 这意味着我们现在可以像下面这样自由使用我们的指令:

    <div exampleDirective>Lorem Ipsum</div>

    Attribute directives, when attached to a host element, look like standard HTML attributes we might set in the course of building a web page. This will not give us any default behavior though — within our directive.ts file, usually in the constructor, we will grab an elementRef to our target element and apply whatever style changes we want to be applied to our targeted element. There is an awful lot that can be done with Attribute directives including stacking multiple on a host element or even having an Attribute directive affect the behavior of another directive but again, outside the scope of this article — if you’re interested, the Angular documentation is a great place to get a better grasp on these.

    属性指令附加到宿主元素后,看起来就像我们在构建网页时可能设置的标准HTML属性。 不过,这不会给我们任何默认行为-在我们的directive.ts文件中,通常是在构造函数中,我们将获取一个elementRef到目标元素,并将想要应用于样式的任何样式更改应用于目标元素。 使用Attribute指令可以完成很多工作,包括在主机元素上堆叠多个指令,甚至让Attribute指令影响另一个指令的行为,但是同样,超出了本文的范围,如果您感兴趣的话,请访问Angular文档是更好地掌握这些内容的好地方。

    Image for post
    Structural directives actually change the DOM rather than components behaviors within the DOM

    Structural directives differ from Attribute directives in that rather than modifying their host element, Structural directives modify the DOM and surrounding elements. Rather than directly accessing the DOM, structural directives allow us to write logic that takes the from of if X, then Y or for each thing, do this and so on. There can only be ONE structural directive per element. Below is an example using NgIf which evaluates an expression and returns a boolean.

    结构化指令与属性指令的不同之处在于, 结构化指令不是修改其宿主元素,而是修改DOM和周围的元素。 结构指令允许我们编写逻辑,而不是直接访问DOM,而该逻辑采用if X, then Y或其他for each thing, do this取值,等等。 每个元素只能有一个结构指令。 以下是使用NgIf的示例,该示例对表达式求值并返回布尔值。

    <div *ngIf="candy = tastesGood">
    Candy always tastes good so this will show.
    </div><div *ngIf="red = blue">
    Red will never equal blue so ngIf evaluates to false.

    Even though these two examples are simplistic pseudo code, they do a good job of showing how we use a structural directive to change the structure of the DOM. It’s worth noting that the div which has the ngIf evaluating to false is not hidden or obscured, it is rather FULLY REMOVED from the DOM. Angular’s default behavior is meant to help us prevent memory leaks and make sure that our app is running as quickly and smoothly as possible. In some situations, it may make more sense to not fully destroy and recreate components and you may want to circumvent this default behavior; this is a consideration that you will be able to make with experience and context within your app.

    即使这两个示例都是简单的伪代码,它们也很好地说明了我们如何使用结构化指令来更改DOM的结构。 值得注意的是,具有ngIf评估为false的div不会被隐藏或掩盖,而是从DOM中完全删除的。 Angular的默认行为旨在帮助我们防止内存泄漏,并确保我们的应用程序尽可能快且平稳地运行。 在某些情况下,不完全销毁和重新创建组件可能更有意义,并且您可能想规避这种默认行为; 这是您可以在应用程序中的经验和上下文中做出的考虑。

    Image for post
    It’s all just sugar

    Finally, we’re ready to talk about the *s all over our apps and unfortunately, this may be the most boring part of the whole article because what the stars really come down to is simple syntactic sugar. When Angular reads our code and goes to compile, our *ngIf (or any other directives) are actually read as:

    最后,我们准备讨论所有应用程序中的*,但是不幸的是,这可能是整篇文章中最无聊的部分,因为真正的含义是简单的语法糖。 当Angular读取我们的代码并进行编译时,我们的* ngIf(或任何其他指令)实际上被读取为:

    <ng-template [ngIf]="tastesGood">
    <div>Candy always tastes good so this will show.</div>

    Those *s serve as a signal to Angular that what we are actually asking for is to take our targeted element, wrap it in an <ng-template> element, and then on the wrapper use ngIf property binding. Even though this example is specific to *ngIf, the behind the scenes behavior of structural directives is largely the same. Let’s pretend we have an array called TMNT with four entries.

    这些*信号向Angular发出信号,我们实际上要的是获取目标元素,将其包装在<ng-template>元素中,然后在包装器上使用ngIf属性绑定。 即使此示例特定于* ngIf,结构指令的幕后行为在很大程度上也相同。 假设我们有一个名为TMNT的数组,其中包含四个条目。

    <table *ngFor="let turtle of TMNT">
    <tr> {{turtle}} </tr>
    </table>//becomes<ng-template ngFor let-turtle [ngForOf]="TMNT">
    <tr> {{turtle}} </tr>

    This is of course nothing more than a pseudo simplification — *ngFor has many more optional args than I have incorporated here as this is meant purely to show you how much syntactic sugar can be provided by a single *.

    当然,这不过是伪简化— * ngFor的可选参数比我在这里结合的要多,因为这纯粹是为了向您展示单个*可以提供多少语法糖。

    Feel free to reach out with any questions, comments or struggles you’ve had learning Angular. I am far from a master but I love to keep paying my learning forward in any way that I can.

    随时与您学习过Angular的任何问题,评论或挣扎联系。 我离大师还很远,但是我喜欢继续以我能做的任何方式继续学习。

    翻译自: https://medium.com/@rossperkel/look-at-the-st-rs-structural-directives-in-angular-ca4b6f59d7f9

    angular 结构型指令

  • Angular结构简单介绍

    2018-03-05 17:21:00
    在当前项目目录下,使用Angular-CLI生成一个组件:heroes ng generate component heroes 主界面(也就是一个主模块+多个单模块,例如我们创建的heroes(单模块也有自己的html\css\ts文件,可以在主...


    ng generate component heroes









    <div class="inCenter">
            Welcome to {{ head }}!
    <!-- 显示 HeroesComponent视图 -->


    .inCenter {
        text-align: center;
        color: #f00;


    import { Component } from '@angular/core';
      // selector:选择器
      selector: 'app-root',
      // 模板地址
      templateUrl: './app.component.html',
      // 样式地址(数组)
      styleUrls: ['./app.component.css']
    export class AppComponent {
      title = 'fcuk';
      head =  '66s';


    Angular CLI AppModule在src/app/app.module.ts创建项目时生成了一个类。这是你选择进入的地方FormsModule。
    // 1.导入模块
    import { BrowserModule } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms'; // <-- NgModel 在这里
    import { NgModule } from '@angular/core';
    // 2.导入组件
    import { AppComponent } from './app.component';
    import { HeroesComponent } from './heroes/heroes.component';
       * AppModule 声明这两个应用程序组件,AppComponent和HeroesComponent。
      declarations: [
      imports: [
         * 然后添加FormsModule到元数据的数组中,
         * 其中包含应用程序需要的外部模块列表。@NgModuleimports
          * 每个组件必须在一个 NgModule中声明。
          * 你没有声明HeroesComponent。那么,为什么该应用程序工作?
          * 它的工作原因是Angular CLI HeroesComponent在AppModule它生成该组件时进行了声明。
          * 打开src/app/app.module.ts并HeroesComponent在顶部附近找到导入。
      providers: [],
      bootstrap: [AppComponent]
    export class AppModule { }


    // 这个是创建的Hero类
    export class Hero{
        id: number;
        name: string;


        heroes works{{hero}}!
    <!-- 显示对象值 -->
    <!-- 格式与 UppercasePipe,你可以创建你自己的格式化字符串、货币金额、日期等 -->
    <h2>{{ hero.name | uppercase }} Details</h2>
    <div><span>id: </span>{{hero.id}}</div>
    <div><span>name: </span>{{hero.name}}</div>
        <input [(ngModel)]="hero.name" placeholder="name">




    import { Component, OnInit } from '@angular/core';
    // 表单模块
    // import { FormsModule } from '@angular/forms';
    // 导入组件hero.js
    import { Hero } from '../hero';
      //在CSS元素选择, 'app-heroes'是相匹配的标识父组件模板内此组件的HTML元素的名称
      selector: 'app-heroes',
      templateUrl: './heroes.component.html',
      styleUrls: ['./heroes.component.css']
    export class HeroesComponent implements OnInit {
      // Hero对象值
      hero: Hero = {
        id: 1,
        name: 'Windstorm'
      constructor() { }
      //这ngOnInit是一个生命周期钩子 Angular ngOnInit在创建组件后立即调用。这是放置初始化逻辑的好地方
      ngOnInit() {



  • Angular结构型指令

    2017-05-08 23:29:00
    2019独角兽企业重金招聘Python工程师标准>>> ...


    结构型指令的职责是HTML布局。 它们塑造或重塑DOM的结构,比如添加、移除或维护这些元素。所有的包括自定义的结构型指令在模版中使用时必须加*前缀

    <div *ngIf="hero" >{{hero.name}}</div>

    星号(*)这个简写方法是一个微语法,而不是通常的模板表达式。 Angular会解开这个语法糖,变成一个<ng-template>标记,包裹着宿主元素及其子元素。


    import ...
    import { TemplateRef, ViewContainerRef } from '@angular/core';
    @Derective({selector: '[指令名]'})
    export class ...
    constructor (
      private templateRef: TemplateRef,
      private viewContainerRef: ViewContainerRef) {}
    @Input('别名')                                //通过viewContainerRef来渲染组件模板内容
      set 绑定的属性名(形参: 值类型boolean) {       //假设这里是boolean类型
        if (形参) {
          this.viewContainerRef.createEmbeddedView(this.templateRef);  //this.templateRef这个组件的模板
        } else {...}





  • 结构型指令 1.*的作用 *ngIf / *ngFor是Angular的指令,*是一个语法糖,避免复杂写ng-template <a *ngIf="user.login">退出</a> 等同于 <ng-template [ngIf]="user.login"> <a>退出</...



    • *ngIf / *ngFor是Angular的指令,*是一个语法糖,避免复杂写ng-template

      <a *ngIf="user.login">退出</a>


      <ng-template [ngIf]="user.login">

    2.Angular Dom操作

    • ViewContainerRef和ElementRef对比

      <!-- 如果想在icon元素同级下面创建一个button元素的子节点,此时button就是ViewContainer,即要在哪个容器里面创建,ElementRef相当于表示button节点,想修改节点属性则用ElementRef,在节点内容创建子视图则使用ViewContainerRef -->
      <button class="fab-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返回的是一个引用

      • 实例代码

            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元素

            selector: 'sample',
            template: `
                <span #test>Test span</span>
        export class SampleComponent implements AfterViewInit {
            constructor(private hostElement: ElementRef) {
                //输出<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中。接下来的示例表示从模板创建一个嵌入式视图,并将其插入标记的特定位置

        <ng-container #test>Test</ng-container>
        <ng-template #templatetest>
        @ViewChild('test', {read: ViewContainerRef}) test: ViewContainerRef;
        @ViewChild('templatetest') templatetest: TemplateRef<any>;
        ngAfterViewInit(): void {
            let view = this.templatetest.createEmbeddedView(null);
      • 删除视图:从DOM中删除一个视图,我们可以使用 detach方法。所有其他方法都是自解释性的,可用于获取索引视图的引用,将视图移到另一个位置,或者从容器中删除所有视图

      • 创建视图:可以使用createComponent()方法或createEmbeddedView()方法进行创建

    • ngTemplateOutlet和ngComponentOutlet

      • ngTemplateOutlet

        • 它将DOM元素标记为 ViewContainer ,并在其中插入一个由模板创建的嵌入视图,而不需要在组件类中显式地这样做。这意味着上面的例子中我们创建了一个视图并将其插入#vc DOM元素,可以这样重写,我们在组件类中不使用任何实例化代码的视图。

              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>
          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—— 创建宿主视图(动态组件)



    • 模块相当于一组具有相同功能的文件的集合,模块将这些文件组织起来

    • 模块的元数据

      imports: []
      declarations: []//当前module内部的组件都需要declarations定义
      entryComponents: [] //表示进来模块的时候就会加载的,而不是调用的时候才去加载,不是显示的表现出来,而是通过某种机制触发的
      exports:[] //如果当前模块的组件希望大家公用的,需要进行export出来,否则别人没法使用
    • forRoot(),forChild()是什么?

      • 点进源文件看的话,其实是两个静态方法(两个工厂)

      • 实例代码

        export class ServicesModule {
            static forRoot():ModuleWithProviders {
                return {
                    ngModule: ServicesModule,
                    providers: []


    • 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>
  • 结构型指令 *是一个语法糖,<a *ngIf="user.login">退出</a>相当于 <ng-template [ngIf]="user.login"> <a>退出</a> </ng-template> 避免了写ng-template。 <ng-...
  • AngularJSAPIDocs WelcometotheAngularJSAPIdocspage.ThesepagescontaintheAngularJSreferencematerialsforversion1.2.6taco-salsafication. 欢迎使用AngularJSAPI文档页,这些页面含有了AngularJS(引用材料为1....
  • Angular目录结构e2e:在e2e/下是端到端测试node_modules:安装的第三方模块都在这,使用npm install安装的1Src:我们项目的所有文件{App:组件,以app.module.ts定义根模块1Assets:静态资源1environments:各个...
  • Angular目录结构

    2020-12-18 11:20:19
    Angular目录结构 1、浅层目录结构 e2e:端到端的测试目录,用于自动测试 node-modules:存放第三方依赖包 src:应用程序源码目录 angular-cli.json:angular命令行工具的配置文件,如果额外引了第三方依赖...
  • 我们已经通过Angular CLI命令行工具创建出来一个全新的Angular项目,要想写项目,首先我们要先搞清楚项目的目录结构是怎样的,每个文件又有什么意义,文件中的代码又起到什么作用。首先看一下整体的目录结构:可以...
  • 目录结构:首层目录:node_modules 第三方依赖包存放目录e2e 端到端的测试目录 用来做自动测试的src 应用源代码目录.angular-cli.json Angular命令行工具的配置文件。后期可能会去修改它,引一些其他的第三方的包 ...
  • 本篇文章主要介绍了详解Angular 自定义结构指令,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Angular项目结构熟悉

    2020-11-30 09:20:48
    Angular项目结构熟悉 Angular 作为前端几大框架之一,且其具体的使用步骤跟vue 非常的相似,如何快速的上手使用,其项目结构图必须先了解,不然看一些教学视频会非常懵逼,所以小编这里就简单的画了一个,希望对正在...
  • Angular 8 结构分析

    2019-12-04 16:18:25
    目录结构分析 详情参考:https://www.angular.cn/guide/file-structure 2.app.module.ts组件分析 定义 AppModule,这个根模块会告诉 Angular 如何组装该应用。 目前,它只声明了 AppComponent。 稍后它还会...
  • Angular项目目录结构详解

    万次阅读 多人点赞 2017-05-05 11:34:39
    在上一篇博客中我们已经通过Angular CLI命令行工具创建出来一个全新的Angular项目,要想写项目,首先我们要先搞清楚项目的目录结构是怎样的,每个文件又有什么意义,文件中的代码又起到什么作用。
  • 分析Angular目录结构

    2018-08-21 07:49:45
    分析Angular目录结构以及Angular Cli生成的基础代码 e2e 端到端的测试目录,用来做自动测试得 node_modules 第三方的依赖包 src 源代码目录 app 包含应用的组件和模块 assets 用来存放静态资源文件 ...


1 2 3 4 5 ... 20
收藏数 1,872
精华内容 748