Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular 之旅(一) #104

Open
reng99 opened this issue Oct 17, 2021 · 0 comments
Open

Angular 之旅(一) #104

reng99 opened this issue Oct 17, 2021 · 0 comments
Labels
blog a single blog

Comments

@reng99
Copy link
Owner

reng99 commented Oct 17, 2021

Angular 是一个应用设计框架与开发平台,用于创建高效、复杂、精美的单页应用。

本文基于个人实际开发项目而产生的实用知识点。

组件重要生命周期

钩子方法 说明
ngOnInit() 组件初始化,只调用一次
ngOnDestroy() 在 Angular 销毁指令或组件之前立即调用

组件展示

  • **
    • demo-show.component.html
    • demo-show.component.less
    • demo-show.component.ts
# demo-show.component.less

#demo {
    background-color: red;
    h1 {
        color: blue;
    }
}
# demo-show.component.html

<div id="demo">
    <h1>This is Demo</h1>
</div>
import { Component } from '@angular/core';

@Component({
    selector: 'demo-show',
    templateUrl: './demo-show.component.html',
    styleUrls: ['./demo-show.component.less']
})
export class DemoShowComponent {
    constructor(){}
    
    ngOninit(){}
    
    ngOnDestroy(){}
}

当然,你可以通过插件生成组件 Angular: Generate a component

组件传值

父组件传值给子组件

compoent-parent-to-child.png

# parent 的 html
<app-item-detail [item]="'current item'"></app-item-detail>

# child 名为 app-item-detail 的 html
<p>Hello, {{item}}.</p>

# child 名为 app-item-detail 的 typescript
import { Input } from '@angular/core'
export class AppItemDetailCompoent {
    @Input() item = '' # 重点
}

子组件传值给父组件

component-child-to-parent.png

# 子组件 item-output.component.html
<label for="item-input">Add an item:</label>
<input type="text" id="item-input" #newItem/>
<button (click)="addNewItem(newItem.value)">Add to parent list</button> # 重点

# 子组件 item-output.compoent.ts
import { Output, EventEmitter } from '@angular/core'
export class ItemOutput {
    @Output() newItemEvent = new EventEmitter<string>(); # 重点
    addNewItem(value: string) {
        this.newItemEvent.emit(value)
    }
}

# 父组件 app.component.html
<item-output (newItemEvent)="addItem($event)"></item-output> # 重点

# 父组件 app.compenent.ts
export class AppComponent {
    items = ['item1', 'item2', 'item3', 'item4'];
    
    addItem(newItem: string) {
        this.items.push(newItem)
    }
}

注意⚠️ @Input@Output 的使用,汇总见图

component-parent-to-back-child.png

内容投影

使用 ng-content 元素, 将希望投影的内容出现在其中。ng-content 只是一个占位符,它不会创建真正的 DOM 元素。

单插槽内容投影

# zippy-basic.component.ts
import { Compoent } from '@angular/core'

@Component({
    selector: 'app-zippy-basic',
    template: `
        <h2>Single-slot content projection</h2>
        <ng-content></ng-content>
    `
})

export class ZippyBasicComponent {}

# app.component.html
<app-zippy-basic>
    <p>Is content projection cool?</p>
</app-zippy-basic>

多插槽内容投影

使用多个 ng-content ,但是有所区分。

# zippy-multislot.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'app-zippy-multislot',
    template: `
        <h2>Multi-slot content projection</h2>
        <ng-content></ng-content>
        <ng-content select="[question]"></ng-content>
    `
})
export class ZippyMultislotComponent {}

# app.component.html
<app-zippy-multislot>
    <p question>
        Is content projection cool?
    </p>
    <p>
        Let's learn about content projection!
    </p>
</app-zippy-multislot>

If、Show 和遍历数据

条件 If ... Else ...

使用 else:

<div *ngIf="isValid; else other_content">
    content here ...
</div>
<ng-template #other_content>
    other content here ...
</ng-template>

使用 then else:

<div *ngIf="isValid; then content else other_content">
    here is ignored
</div>
<ng-template #content>content here ...</ng-template>
<ng-template #other_content>other content here ...</ng-template>

或者使用 then:

<div *ngIf="isValid; then content">
    content here ...
</div>
<ng-template #content>
    then content here ...
</ng-template>

使用 Show

Show 的效果模拟可以使用 If 去完成,但是会造成了 DOM 的回流。为了避免这种情况,我们使用 hidden 属性。

<p [hidden]="isAdmin">管理员</p>
<p [hidden]="!isAdmin">普通用户</p>

遍历数据

使用 ngFor

<li *ngFor="let item of items" class="{{item.isActive ? 'active-li' : 'default-li'}}"></li>

引用子组件

这里讲父组件调用子组件的方法,调用属性大同小异。

使用 viewChild 装饰器。

# app-child.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
    selector: 'app-child',
    templateUrl: './app-child.component.html',
    styleUrls: ['./app-child.component.less']
})
export class AppChildComponent implements OnInit {
    construtor() {  }
    
    ngOnInit() {  }
    
    greeting(name: string) {
        console.log(`hello ${name}`)
    }
}

# app.component.html
<app-child #child></app-child>

# app.component.ts
@ViewChild('child') child: AppChildComponent; # 重点

ngOnInit() {
    this.child.greeting('World');
}

后话

@reng99 reng99 added the blog a single blog label Mar 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog a single blog
Projects
None yet
Development

No branches or pull requests

1 participant