美文网首页我爱编程现代前端指南!
Angular 中 ContentChild & Content

Angular 中 ContentChild & Content

作者: moving_mG | 来源:发表于2018-04-12 16:43 被阅读0次

    Content顾名思义是内容,它与放置在<ng-content></ng-content>里面的投影内容息息相关。


    1. 回顾一下ng-content

    greet.component.ts

    import { Component } from '@angular/core';
    
    @Component({
        selector: 'exe-greet',
        template: `
        <div class="border"> 
            <ng-content></ng-content> // 投影处
        </div>
        `,
        styles: [` .border { border: 2px solid #eee; } `]
    })
    export class GreetComponent { }
    

    app.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
        <h4>Welcome to Angular World</h4>
        <exe-greet>
          <p>Hello Minghao</p>  // 在exe-greet标签中放置的内容将会投影到ng-content处
        </exe-greet>
      `,
    })
    export class AppComponent { }
    

    此时网页上输出的内容,假设我们将 my-app 的template内容显示出来

        <h4>Welcome to Angular World</h4>
        <div class="border"> 
            <p>Hello Minghao</p> // exe-greet的内容如左边所示
        </div>
    

    2. ng-content支持select属性

    有人可能会说上面那样太简单了,实际需求中可能会稍微复杂一些,要插入的内容需要自定义,甚至是放入某些节点里面包裹起来,而且可能有不同的组件需要用到greet这个组件,行,那我们来改进一下。

    import { Component } from '@angular/core';
    
    @Component({
        selector: 'exe-greet',
        template: `
        <div class="border">
            <p>Greet Component</p>  
            <div style="border: 1px solid #666;margin: 4px;">
                 <div style="border: 1px solid red;margin: 5px;">
                    <ng-content select="header"></ng-content> // 标签选择器
                 </div>
                 <div style="border: 1px solid green;margin: 5px;">
                    <ng-content select=".card_body"></ng-content> // 类选择器
                </div>
                <div style="border: 1px solid blue;margin: 5px;">
                   <ng-content select="footer"></ng-content> // 标签选择器
                </div>
           </div>
        </div>
        `,
        styles: [` .border { border: 2px solid #eee; } `]
    })
    export class GreetComponent{ }
    

    GreetComponent 组件已经调整好了,现在剩下的问题就是如何从父级组件动态的抽取各个部分的内容。幸运的是,ng-content 指令支持 select 属性,它允许我们设定抽取的内容,更强大的是它支持我们常用的选择器类型,如标签选择器、类选择器、ID选择器、属性选择器等。

    下面来改善一下父模板app.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
        <h4>Welcome to Angular World</h4>
        <exe-greet>
          <header>Card Header</header>
              <div class="card_body">Card Body</div>
          <footer>Card Footer</footer>
        </exe-greet>
      `,
    })
    export class AppComponent { }
    

    此时网页上输出的内容,假设我们将 my-app 的template内容显示出来

        <h4>Welcome to Angular World</h4>
        <div class="border">
            <p>Greet Component</p>  
            <div style="border: 1px solid #666;margin: 4px;">
                 <div style="border: 1px solid red;margin: 5px;">
                    <header>Card Header</header> // 标签选择器
                 </div>
                 <div style="border: 1px solid green;margin: 5px;">
                    <div class="card_body">Card Body</div> // 类选择器
                </div>
                <div style="border: 1px solid blue;margin: 5px;">
                    <footer>Card Footer</footer> // 标签选择器
                </div>
           </div>
        </div>
    

    3. 切入正题,谈谈@ContentChild

    child.component.ts

    import { Component } from '@angular/core';
    
    @Component({
        selector: 'exe-child',
        template: `
          <p>Child Component</p>  
        `
    })
    export class ChildComponent {
        name: string = 'child-component';
    }
    

    parent.component.ts

    import { Component, ContentChild, AfterContentInit } from '@angular/core';
    import { ChildComponent } from './child.component';
    
    @Component({
        selector: 'exe-parent',
        template: `
          <p>Parent Component</p>  
          <ng-content></ng-content>
        `
    })
    export class ParentComponent implements AfterContentInit {
        @ContentChild(ChildComponent)
        childCmp: ChildComponent;
    
        ngAfterContentInit() {
            console.dir(this.childCmp);
        }
    }
    

    app.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
        <h4>Welcome to Angular World</h4>
        <exe-parent>
          <exe-child></exe-child>
        </exe-parent>
      `,
    })
    export class AppComponent { }
    

    以上代码运行后,控制台的输出结果:


    ContentChild.png

    ContentChildren

    ContentChildren 属性装饰器用来从通过 Content Projection 方式设置的视图中获取匹配的多个元素,返回的结果是一个 QueryList 集合。

    parent.component.ts

    import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
    import { ChildComponent } from './child.component';
    
    @Component({
        selector: 'exe-parent',
        template: `
          <p>Parent Component</p>  
          <ng-content></ng-content>
        `
    })
    export class ParentComponent implements AfterContentInit {
        
        @ContentChildren(ChildComponent)
        childCmps: QueryList<ChildComponent>;
    
        ngAfterContentInit() {
            console.dir(this.childCmps);
        }
    }
    

    app.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
        <h4>Welcome to Angular World</h4>
        <exe-parent>
          <exe-child></exe-child>
          <exe-child></exe-child>
        </exe-parent>
      `,
    })
    export class AppComponent { }
    

    以上代码运行后,控制台的输出结果:


    ContentChild2.png

    Something else

    • ContentChildren 与 ViewChildren 的定义
      • 在 host 元素 <opening> 和 </closing> 标签中被称为 Content Children

      • 在组件的模板中定义的内容,它是组件的一部分,被称为 View Children

    • ContentChild 与 ViewChild 的异同点
    • 相同点

    1.都是属性装饰器

    2.都有对应的复数形式装饰器:ContentChildren、ViewChildren

    3.都支持 Type<any>|Function|string 类型的选择器

    • 不同点

    1.ContentChild 用来从通过 Content Projection 方式 (ng-content) 设置的视图中获取匹配的元素

    2.ViewChild 用来从模板视图中获取匹配的元素

    3.在父组件的 ngAfterContentInit 生命周期钩子中才能成功获取通过 ContentChild 查询的元素

    4.在父组件的 ngAfterViewInit 生命周期钩子中才能成功获取通过 ViewChild 查询的元素

    (reference by semlinker)

    相关文章

      网友评论

        本文标题:Angular 中 ContentChild & Content

        本文链接:https://www.haomeiwen.com/subject/tdxfkftx.html