三天入手angular9 全乾貨 基礎篇(二)

注:默認已有紮實的vue功底

循環體的根元素

template ng-container

<ng-container *ngIf="lessons">
    <div class="lesson" *ngFor="let lesson of lessons">
        <div class="lesson-detail">
            {{lesson | json}}
        </div>
    </div>
</ng-container>

插槽

slot ngTemplateOutlet

<ng-container *ngTemplateOutlet="aaa; context: {{$implicit: '我是默認值,隱式定義,不需要賦值,對應let-name', diyValue: '我是自定義對象,需要賦值'}}" ></ng-container>

<ng-template #aaa let-name let-diyValue=”diyValue“>
	默認值- {{name}}
    賦值- {{diyValue}}
</ng-template>

#aaa叫做模板引用變量
let-name叫做模板輸入變量
這裏的理解是,

ng-template插入對應的ng-container的引用標記中,

#aaa插入到對應的*ngTemplateOutlet="aaa"

然後將變量``傳入模板內,模板內接受變量進行賦值let-diyValue="xx",`

完了在模板作用域內使用該變量{{diyValue}}`

自定義組件

引用

<ng-container *ngFor="let item of [1,2,3]; let idx=index">
    <app-template-test [dTemplate]="tpl">
      <ng-template #tpl>
        <div>
          <p>我進來看看{{item}}</p>
          <p>我也進來康康{{idx}}</p>
        </div>
      </ng-template>
    </app-template-test>
  </ng-container>

ts

import { Component, OnInit, Input, TemplateRef } from '@angular/core';

@Component({
  selector: 'app-template-test',
  templateUrl: './template-test.component.html',
  styleUrls: ['./template-test.component.css']
})
export class TemplateTestComponent implements OnInit {
  @Input() dTemplate: TemplateRef<void>; // 接受外部模板
  
  constructor() { }

  ngOnInit(): void {
  }

}

html

<div>
  自己寫的組件
  blablabla
  <ng-template #defaultContent>
    我是默認顯示的內容
  </ng-template>
  // 使用外部模板或者使用自定義模板
  <ng-template [ngTemplateOutlet]="dTemplate || defaultContent"></ng-template>
</div>

組件傳值

父傳子

方法一 在父組件上設置子組件的屬性【類似vue的props傳參】
父組件綁定信息

<app-child childTitle="可設置子組件標題"></app-child>

子組件接收消息

import { Component, OnInit, Input } from '@angular/core';
@Input childTitle: string; // 類似vue的props接收參數

方法二 父組件調用子組件的方法
父組件觸發消息 【類似vue的ref.methods的寫法,區別是直接在模板調用】

<app-child #child></app-child> <button (click)="child.childPrint()"></button>

子組件接收消息

childPrint() {
  alert("來自子組件的打印");
}

子傳父

子組件向父組件傳遞信息
方法一 使用 EventEmitter
子組件使用 EventEmitter 傳遞消息

【類似vue的this.emit(methodsName,data),<div@methodsName="parentMethod(emit(methodsName, data), `<div @methodsName="parentMethod(event)">點我`】

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
...
@Output() initEmit = new EventEmitter<string>();
ngOnInit() {
  this.initEmit.emit("子組件初始化成功");
}
...

父組件接收消息

<app-child (initEmit)="accept($event)"></app-child>
accept(msg:string) {
  alert(msg);
} 

方法二 使用 ViewChild
子組件提供傳遞參數的函數 【類似vue的ref操作,調用子組件方法來傳數據】

sendInfo() {
  return 'Message from child 1.';
}
// 父組件使用 ViewChild 觸發並接收信息
<button (click)="getInfo()">獲取子組件1號的信息</button>
import { Component, OnInit, ViewChild } from '@angular/core';
...
@ViewChild(ChildFirstComponent) private childcomponent: ChildFirstComponent;
getInfo() {
  this.info = this.childcomponent.sendInfo();
}

非父子組件通信

方法一:server

缺點:需要雙向的觸發(發送信息 / 接收信息)

service.ts 一個公共的state文件

import { Component, Injectable, EventEmitter } from "@angular/core";
@Injectable() // 可注入的服務
export class myService {
  public info: string = ""; // 相對於vue的state
  constructor() {}
}

組件 1 向 service 傳遞信息

import { myService } from '../../service/myService.service'; // 在組件中引入服務
...
constructor(
  public service: myService // 實例化服務
) { }

changeInfo() {
  this.service.info = this.service.info + "1234"; // 修改服務
}
...

組件 2 從 service 獲取信息

import { myService } from '../../service/myService.service';
...
constructor(
  public service: myService
) { }

showInfo() {
  alert(this.service.info);
}
...

方法二: 使用 BehaviorSubject

優點:真正的發佈訂閱模式,當數據改變時,訂閱者也能得到響應

service

import { BehaviorSubject } from 'rxjs';
...
public messageSource = new BehaviorSubject<string>('Start');
changemessage(message: string): void {
  this.messageSource.next(message);
}

組件調用 service 的方法傳信息和接收信息

changeInfo() {
  this.communication.changemessage('Message from child 1.');
}
ngOnInit() {
  this.communication.messageSource.subscribe(Message => {
    window.alert(Message);
    this.info = Message;
  });
}

其他的通信方式

  • 路由傳值
  • cookie、session、storage

內容投影

ng-content 【類似vue的slot】

語法:

<ng-content select=".class,#id,select">

ng-content提供佔位,select屬性選擇站位元素,相對於slot的名字。

創建組件

ng g c content-part-layout

ng g c content-part-a

ng g c content-part-b

content-part-layout

<p>content-part-layout works!</p>
<div>
  <div>主頁面</div>
  <app-content-part-a></app-content-part-a>
  <app-content-part-b></app-content-part-b>
  <div> a嵌套b </div>
  <app-content-part-a>
    <div class="mydiv">我是a頁面</div>
    <app-content-part-b></app-content-part-b>
  </app-content-part-a>
</div>

content-part-a

<p>content-part-a works!</p>
<ng-content select=".mydiv"></ng-content>
<ng-content select="app-content-part-b"></ng-content>

app.component.html

<!-- 內容投影,組件嵌套 -->
<app-content-part-layout></app-content-part-layout>
 <div class="mydiv">我是a頁面</div>
 <app-content-part-b></app-content-part-b>

上面這段代碼會帶入到content-part-a裏面對應的select選擇名所在的ng-content位置

例子代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章