• 技术文章 >web前端 >js教程

    聊聊angular中进行内容投影的方法

    青灯夜游青灯夜游2022-05-12 10:41:28原创125
    本篇文章带大家聊聊angular中的内容投影,介绍一下使用ng-content进行内容投影的方法,并了解有条件内容投影的实现方法,希望对大家有所帮助!

    一、 ng-content 进行内容投影

    1.1 ng-content

    ng-content 元素是一个用来插入外部或者动态内容的占位符。父组件将外部内容传递给子组件,当 Angular 解析模板时,就会在子组件模板中 ng-content 出现的地方插入外部内容。【相关教程推荐:《angular教程》】

    我们可以使用内容投影来创建可重用的组件。这些组件有相似的逻辑和布局,并且可以在许多地方使用。一般我们在封装一些公共组件的时候经常会用到。

    1.2 为什么使用内容投影

    定义一个 button 组件:

    button-component.ts

    @Component({
        selector: '[appButton]',
        template: `
        <span class="icon-search"></span>
    `
    })
    export class AppButtonComponent {}

    这个 button 组件的目的是在按钮内部加一个搜索的图标,我们实际使用如下:

    <button appButton>click</button>

    我们发现组件只会展示搜索图标, 按钮的文本不会展示,能你会想到最常使用的 @Input 装饰器,但是如果我们不只是想传文本进来,而是传一段 html 进来呢?此时就会用到 ng-content

    1.3 单插槽内容投影

    内容投影的最基本形式是单插槽内容投影

    单插槽内容投影是指创建一个组件,我们可以在其中投影一个组件。

    以 button 组件为例,创建一个单槽内容投影:

    button-component.ts

    @Component({
        selector: '[appButton]',
        template: `
        <span class="icon-search"></span> <ng-content></ng-content>
    `
    })
    export class AppButtonComponent {}

    实际使用如下:

    <button appButton>click</button>

    可以发现,现在这个 button 组件的效果是即显示了搜索图标,又显示了按钮的文本(click)。即把 <button appButton></button> 中间的内容 投影 到了组件的 <ng-content></ng-content> 位置。

    ng-content 元素是一个占位符,它不会创建真正的 DOM 元素。ng-content 的那些自定义属性将被忽略。

    1.4 多插槽内容投影

    一个组件可以具有多个插槽,每个插槽可以指定一个 CSS 选择器,该选择器会决定将哪些内容放入该插槽。该模式称为多插槽内容投影。使用此模式,我们必须指定希望投影内容出现在的位置。可以通过使用 ng-contentselect 属性来完成此任务。

    以 button 组件为例,创建一个多槽内容投影:

    button-component.ts

    @Component({
        selector: '[appButton]',
        template: `
        <span class="icon-search"></span> <ng-content select="[shuxing]"></ng-content> <ng-content select="p"></ng-content> <ng-content select=".lei"></ng-content>
    `
    })
    export class AppButtonComponent {}

    实际使用如下:

    <button appButton>
    <p>click</p> <span shuxing>me</span> <span class="lei">here</span>
    </button>

    1.5 ngProjectAs

    在某些情况下,我们需要使用 ng-container 把一些内容包裹起来传递到组件中。大多数情况是因为我们需要使用结构型指令像 ngIf 或者 ngSwitch 等。。

    在下面的例子中,我们将 header 包裹在了 ng-container 中。

    @Component({
        selector: 'app-card',
        template: `
    		<div class="card">
    		  <div class="header">
    		    <ng-content select="header"></ng-content>
    		  </div>
    		  <div class="content">
    		    <ng-content select="content"></ng-content>
    		  </div>
    		  <div class="footer">
    		    <ng-content select="footer"></ng-content>
    		  </div>
    		  <ng-content></ng-content>
    		</div>
    `
    })
    export class AppCardComponent {}

    使用:

    <app-card>
      <ng-container>
        <header>
          <h1>Angular</h1>
        </header>
      </ng-container>
      <content>One framework. Mobile & desktop.</content>
      <footer><b>Super-powered by Google </b></footer>
    </app-card>

    由于 ng-container 的存在,header 部分并没有被渲染到我们想要渲染的插槽中,而是渲染到了没有提供任何 selectorng-content 中。
    在这种情况下,我们可以使用 ngProjectAs 属性。
    在上面的 ng-container 加上这个属性,就可以按照我们的期望来渲染了。

    <app-card>
      <ng-container ngProjectAs='header'>
        <header>
          <h1>Angular</h1>
        </header>
      </ng-container>
      <content>One framework. Mobile & desktop.</content>
      <footer><b>Super-powered by Google </b></footer>
    </app-card>

    二、 有条件的内容投影

    如果你的元件需要有条件地渲染内容或多次渲染内容,则应配置该元件以接受一个 ng-template 元素,其中包含要有条件渲染的内容。

    在这种情况下,不建议使用 ng-content 元素,因为只要元件的使用者提供了内容,即使该元件从未定义 ng-content 元素或该 ng-content 元素位于 ngIf 语句的内部,该内容也总会被初始化。

    使用 ng-template 元素,你可以让元件根据你想要的任何条件显式渲染内容,并可以进行多次渲染。在显式渲染 ng-template 元素之前,Angular 不会初始化该元素的内容。

    2.1 ng-container

    既不是一个组件,也不是一个指令,仅仅是一个特殊的tag而已。 使用 ng-container 渲染所包含的模板内容,不包含自身。

    <div>
      <ng-container>
        <p>My name is wyl.</p>
        <p>What is you name?</p>
      </ng-container>
    </div>
    <div>
      <p>My name is wyl.</p>
      <p>What is you name?</p>
    </div>
    <ul>
      <ng-container *ngFor="let item of items">
        <li>{{ item .name}}</li>
        <li>{{ item .age}}</li>
        <li>{{ item .sex}}</li>
      </ng-container>
    </ul>

    另外,ng 中常见错误之一的 forif 不能写在同一标签上(在一个宿主元素上只能应用一个结构型指令),利用 ng-container 标签可以在实现功能的基础上减少层级的嵌套。

    2.2 ng-template

    先来看下面一段代码

    <ng-template>
        <p> In template, no attributes. </p>
    </ng-template>
    
    <ng-container>
        <p> In ng-container, no attributes. </p>
    </ng-container>

    浏览器输出结果是:

    In ng-container, no attributes.

    <ng-template> 中的内容不会显示。当在上面的模板中添加 ngIf 指令:

    <ng-template [ngIf]="true">
       <p> ngIf with a ng-template.</p>
    </ng-template>
    
    <ng-container *ngIf="true">
       <p> ngIf with an ng-container.</p>
    </ng-container>

    浏览器输出结果是:

    ngIf with a ng-template.
    ngIf with an ng-container.

    2.3 ng-template<ng-container> 的配合使用

    <ng-container *ngIf="showSearchBread; else tplSearchEmpty">
         暂时搜索不到您要的数据喔
    </ng-container>
    <ng-template #tplSearchEmpty>
         快快开始获取吧!
    </ng-template>

    2.4 ngTemplateOutlet

    插入 ng-template 创建的内嵌视图。 ngTemplateOutlet 是一个结构型指令,接收一个 TemplateRef 类型的值;

    <div *ngTemplateOutlet="tpl1"></div>
    <ng-template #tpl1>
      <span>I am span in template {{title}}</span>
    </ng-template>

    *ngTemplateOutlet = "templateRefExp; content: contentExp "

    使用如下:

    @Component({
      selector: 'ng-template-outlet-example',
      template: `
        <ng-container *ngTemplateOutlet="greet"></ng-container>
        <hr>
        <ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container>
        <hr>
        <ng-container *ngTemplateOutlet="svk; context: myContext"></ng-container>
        <hr>
        <ng-template #greet><span>Hello</span></ng-template>
        <ng-template #eng let-name><span>Hello {{name}}!</span></ng-template>
        <ng-template #svk let-person="localSk"><span>Ahoj {{person}}!</span></ng-template>
    `
    })
    class NgTemplateOutletExample {
      myContext = {$implicit: 'World', localSk: 'Svet'};
    }

    2.5 利用 ngTemplateOutlet 进行内容投影

    @Component({
        selector: 'app-card',
        template: `
    		<div class="card">
    		  <div class="header">
    		  	<ng-container *ngTemplateOutlet="headerTemplate; context: { $implicit: title, index: otherDate }"></ng-container>
    		  </div>
    		</div>
    `
    })
    export class AppCardComponent {
    
    	@ContentChild('header', { static: true }) headerTemplate: TemplateRef<any>;
    
    	public title = 'Test';
    	public otherDate = {
    	 	auth: 'me',
    	 	name: 'appCard'
    	};
    }

    使用

    <app-card>
      <ng-template #header let-label let-item="otherDate">
        <h1>Angular</h1> {{label}} (Test) and  {{otherDate | json}} ({auth: 'me', name: 'appCard'})
      </ng-template>
    </app-card>

    更多编程相关知识,请访问:编程教学!!

    以上就是聊聊angular中进行内容投影的方法的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:Angular Angular.js
    上一篇:浅析Angular变更检测机制,聊聊如何进行性能优化? 下一篇:一篇搞定JavaScript循环
    千万级数据并发解决方案

    相关文章推荐

    • 一文浅析Angular中的响应式表单• 聊聊在Angular项目中怎么实现权限控制?• 什么是管道?浅析Angular中的管道(PIPE)• Angular项目如何上线?结合nginx来聊聊上线流程!• Angular知识点分享:聊聊表单、管道、绑定、指令、通信和周期• 浅析Angular变更检测机制,聊聊如何进行性能优化?
    1/1

    PHP中文网