zoukankan      html  css  js  c++  java
  • Angular6 学习笔记——内容投影, ViewChild和ContentChild

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址:

    https://www.angular.cn/guide/template-syntax

    http://www.ngfans.net/topic/12/post/2

    系列目录

    (1)组件详解之模板语法

    (2)组件详解之组件通讯

    (3)内容投影, ViewChild和ContentChild

    (4)指令

    (5)路由

    内容投影

    1为什么需要内容投影?

    一个事物的出现,必然存在它所能解决的问题,让我们先从问题出发吧:

    大家应该都知道,在html规范里面,它定义了非常多的标签,在这些标签里面,相同标签之间的嵌套,不同标签之间的嵌套,是十分常见,并且可行

    同时,在Angular里面,我们可以通过自定义标签的方式引用组件,那么这里的标签能否像原生的html标签一样,来嵌入html标签,或者嵌套其他组件标签呢?

    于是就引入我们今天的主要问题,用一个详细的例子来描述吧:

    假设存在父组件Content,和它下面2个子组件PartA和PartB,自定义标签分别为:<app-content>,<app-content-part-a>,<app-content-part-b>,目录结构如下

    如果想在父组件的视图里面,完成下面的内容,是否可行呢?

     content.component.html 

    1
    <div> 2 <div>Content</div> 3 <div> 4 <app-content-part-a> 5 <h1>PartA--start</h1> 6 <app-content-part-b></app-content-part-b> 7 <span>PartA--end</span> 8 </app-content-part-a> 9 </div> 10 </div>

    这样是不行的,其结果只会显示自定义的组件<app-content-part-a>自身的内容,因为自定义组件标签会忽略嵌套其中的html原生标签或者其他的自定义组件标签,从而使它们无法产生任何效果

    2如何使用内容投影?

    上述问题通过内容投影则能够解决,那么如何使用内容投影呢?

    只需要在组件PartA的视图里面做一些改动,内容如下

     part-a.component.html

    1
    <div> 2 <div> 3 <ng-content select="h1"></ng-content> 4 </div> 5 <div> 6 <ng-content select="app-content-part-b"></ng-content> 7 </div> 8 <div> 9 <ng-content select="span"></ng-content> 10 </div> 11 </div>

    经过这样的修改,上述想要实现的效果就可以达到

    那么内容投影是如何工作的呢?

    首先通过angular里面的一个指令ng-content,实现占位,再通过select,达到选择器的作用,这样在组件生命周期过程,初始渲染投影内容的时候,就能够将对应的内容投影到特定的位置,这就是内容投影工作的简单描述

    组件里面嵌套组件,之间的通讯问题可以参考组件间的通讯

    ContentChild和ViewChild                                                                                 

    首先做个简单的介绍:

    ContentChild:与内容子节点有关,操作投影进来的内容;

    ViewChild:与视图子节点有关,操作自身的视图内容;

    在上一部分,我们通过内容投影,让自定义的组件标签能够嵌入html标签或自定义组件标签,那么它如何操作投影进来的内容呢?

    还是以上述内容为例,从实际的问题出发:假设嵌入的自定义组件标签<app-content-part-b>里面声明了一个方法func(),那么如何在<app-content-part-a>里面去操作这个方法呢?
    上面说过,ContentChild是操作投影进来的内容,那么在这里我们也可以通过它解决问题,在组件PartA内,通过ContentChild获取投影进来的组件PartB,并对它进行操作(部分代码在上一部分已经贴出,这一部分不予重复),代码如下

     part-b.component.ts

    1
    import { Component, OnInit,Output} from '@angular/core'; 2 3 @Component({ 4 selector: 'app-content-part-b', 5 templateUrl: './part-b.component.html', 6 styleUrls: ['./part-b.component.scss'] 7 }) 8 export class PartBComponent implements OnInit { 9 constructor() { } 10 11 ngOnInit() { 12 } 13 14 public func():void{ 15 console.log("PartB"); 16 } 17 }
     part-a.component.ts

    1
    import { Component, OnInit, ContentChild } from '@angular/core'; 2 import { PartBComponent } from '../part-b/part-b.component'; 3 4 @Component({ 5 selector: 'app-content-part-a', 6 templateUrl: './part-a.component.html', 7 styleUrls: ['./part-a.component.scss'] 8 }) 9 export class PartAComponent implements OnInit { 10 11 @ContentChild(PartBComponent) PartB:PartBComponent 12 13 constructor() { } 14 15 ngOnInit() {} 16 17 ngAfterContentInit(): void { 18 this.PartB.func(); 19 } 20 }

    这里需要注意一点:在组件的生命周期里面,有一个钩子ngAfterContentInit()是与投影内容初始化有关,所以我们有关投影的内容操作尽量放在它初始化完成之后进行

     如果理解了ContentChild的用法,那么ViewChild几乎没有理解难度,他们的差异不大,所不同的是:

      1ViewChild是操作视图本身存在的节点,而不是投影进来的内容

      2ngAfterContentInit()对应的是ngAfterViewInit()(视图节点初始化是在投影内容初始化之后)

    其他没有什么不同,这里我就不再赘述

     ContentChildViewChild还存在复数的形式,即ContentChildrenViewChildren,它们取到的是节点的一个集合,其他的没有什么区别

    写法如下:

     1 import { Component, OnInit, ContentChild,ContentChildren ,QueryList } from '@angular/core';
     2 import { PartBComponent } from '../part-b/part-b.component';
     3 
     4 @Component({
     5   selector: 'app-content-part-a',
     6   templateUrl: './part-a.component.html',
     7   styleUrls: ['./part-a.component.scss']
     8 })
     9 export class PartAComponent implements OnInit {
    10 
    11 @ContentChildren(PartBComponent)
    12 PartBs: QueryList<PartBComponent>;
    13 
    14   constructor() { }
    15 
    16   ngOnInit() {}
    17 
    18 }

    上述代码中PartBs是组件PartB的一个集合,这就是复数的用法,ViewChildren不再赘述

     (终)

    文档信息


    感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章页面中给出作者和原文连接
  • 相关阅读:
    基于webpack的react脚手架
    关于密码的简单加密
    移动端日期控件
    JS中如何巧妙的用事件委托
    JS中关于正则的巧妙操作
    call,apply,bind
    vue常用笔记
    高性能的js第三方库——lodash、 Underscore、async、md5及moment
    Nightwatch——自动化测试(端对端e2e)
    for循环的耗时问题
  • 原文地址:https://www.cnblogs.com/banluduxing/p/10394387.html
Copyright © 2011-2022 走看看