angular8 平常開發填坑指南

1.else使用

  • 語法糖else
<div *ngIf="isLoggedIn; else loggedOut">
   Welcome back, friend.
   </div>

   <ng-template #loggedOut>
   Please friend, login.
   </ng-template>
複製代碼
  • code 等同於下方
<ng-template [ngIf]="isLoggedIn" [ngIfElse]="loggedOut">
 Welcome back, friend.
</ng-template>

<ng-template #loggedOut>
 Please friend, login.
</ng-template>
複製代碼
  • 在高級一點:
<ng-container *ngIf="isLoggedIn;then loggedIn;loggedOut">
<ng-container>

<ng-template #loggedIn>
 Welcome back, friend.
</ng-template>

<ng-template #loggedOut>
 Please friend, login.
</ng-template>
複製代碼

2.ng-show廢棄

<div [hidden]="!isLoggedIn">
 Welcome back, friend.
</div>
複製代碼

3.angular中使用angularjs組件

  • angularjs組件
export const heroDetail = {
  bindings: {
    hero: '<',
    deleted: '&'
  },
  template: `
    <h2>{{$ctrl.hero.name}} details!</h2>
    <div><label>id: </label>{{$ctrl.hero.id}}</div>
    <button ng-click="$ctrl.onDelete()">Delete</button>
  `,
  controller: function() {
    this.onDelete = () => {
      this.deleted(this.hero);
    };
  }
};
複製代碼
  • 定義angular指令
import { Directive, ElementRef, Injector, Input, Output, EventEmitter } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';
import { Hero } from '../hero';

@Directive({
  selector: 'hero-detail'
})
export class HeroDetailDirective extends UpgradeComponent { 
 # 須要對應於angularjs組件定義的數據綁定
  @Input() hero: Hero;
  @Output() deleted: EventEmitter<Hero>;

  constructor(elementRef: ElementRef, injector: Injector) {
    super('heroDetail', elementRef, injector);
  }
} 
複製代碼
  • 使用指令,引用angularjs組件
import { Component } from '@angular/core';
import { Hero } from '../hero';

@Component({
  selector: 'my-container',
  template: `
    <h1>Tour of Heroes</h1>
    <hero-detail [hero]="hero"
                 (deleted)="heroDeleted($event)">
    </hero-detail>
  `
})
export class ContainerComponent {
  hero = new Hero(1, 'Windstorm');
  heroDeleted(hero: Hero) {
    hero.name = 'Ex-' + hero.name;
  }
}
複製代碼

4.經常使用模板語法

  • 結構指令:css

    • 列表渲染
    <li *ngFor="let hero of heroes">
        {{ hero }}
        </li>
    複製代碼
    • 條件渲染
    <li *ngIf="isHidden">
        {{ hero }}
    </li>
    複製代碼
  • 屬性指令:html

    • 數據單向輸入
    # 動態綁定,更新會觸發對應子組件
     <app-hero-detail [hero]="currentHero"></app-hero-detail>
     
     # 綁定字符串,非變量值
     <app-item-detail childItem="parentItem"></app-item-detail>
    複製代碼
    • 事件反饋
    <w-button (click)="handlerClick" />
     
     # 雙向數據綁定
     <input [(ngModel)]="currentItem.name">
    
     # 等效於
     <input [value]="currentItem.name"
        (input)="currentItem.name=$event.target.value" >
    複製代碼
    • 屬性添加
    <button [attr.aria-label]="help">help</button>
    
    <div [class.special]="isSpecial">Special</div>
    
    <button [style.color]="isSpecial ? 'red' : 'green'">
    
    <button [class]="{foo: true, bar: false}" />
    複製代碼
    • 自定義雙向數據綁定 - x和xChange
    import { Component, Input, Output, EventEmitter } from '@angular/core';
    
     @Component({
        selector: 'app-sizer',
        templateUrl: './sizer.component.html',
        styleUrls: ['./sizer.component.css']
     })
     export class SizerComponent {
    
    
     @Input()  size: number | string;
     @Output() sizeChange = new EventEmitter<number>();
    
     dec() { this.resize(-1); }
     inc() { this.resize(+1); }
    
     resize(delta: number) {
         this.size = Math.min(40, Math.max(8, +this.size + delta));
         this.sizeChange.emit(this.size);
     }
    
     }
    
     # html
     <app-sizer [(size)]="fontSizePx"></app-sizer> 等效於
     
     <app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer>
    複製代碼

5.ng-template

<div *ngIf="isLoggedIn">
    Welcome back, friend.
    </div>
    # 等效於
    <ng-template [ngIf]="isLoggedIn">
        Please friend, login.
    </ng-template>
複製代碼

6.ng-content

# html
	
  <fa-input icon="envelope">
     <i class="fa fa-envelope"></i>
     <input inputRef type="email" placeholder="Email">
  </fa-input>

# js component 
@Component({
  selector: 'fa-input',
  template: `
    <ng-content ></ng-content>  # 匹配fa-input全部其餘的沒有指定匹配的
    <ng-content select="input"></ng-content> # 匹配fa-input中特定的input標籤
  `})
export class FaInputComponent {
   ...
}
複製代碼

7.inject 單例模式

  • 單例模式
import { Injectable } from '@angular/core';

# inject root 利用webpack tree-shaking,優化打包
@Injectable({
    providedIn: 'root',
})
export class UserService {
}

複製代碼
  • privoder配置
@NgModule({
...
providers: [UserService],
...
})
複製代碼
  • 若是二者都提供了,那麼請注意,從UserService中讀取內存數據,可能讀取不到!!!

8.angularjs ui-grid問題

  • 使用技術升級-ag-grid
  • 使用組件升級方案,參考總結3

10.Render2 , 替代jquery

#html 
<div #mydiv><input></div>

# js 
@ViewChild('mydiv') mydiv: ElementRef 
constructor( 
    private el:ElementRef,
    private renderer2: Renderer2){
}
ngOnInit(){
    this.renderer2.setStyle(this.el.nativeElement.querySelector('.btn1'),'background','green');
}

# 儘可能減小應用層與渲染層之間強耦合關係, 推薦下方的render2 
複製代碼
# render2 api
abstract data: {...}
  destroyNode: ((node: any) => void) | null
  abstract destroy(): void
  abstract createElement(name: string, namespace?: string): any
  abstract createComment(value: string): any
  abstract createText(value: string): any
  abstract appendChild(parent: any, newChild: any): void
  abstract insertBefore(parent: any, newChild: any, refChild: any): void
  abstract removeChild(parent: any, oldChild: any, isHostElement?: boolean): void
  abstract selectRootElement(selectorOrNode: any, preserveContent?: boolean): any
  abstract parentNode(node: any): any
  abstract nextSibling(node: any): any
  abstract setAttribute(el: any, name: string, value: string, namespace?: string): void
  abstract removeAttribute(el: any, name: string, namespace?: string): void
  abstract addClass(el: any, name: string): void
  abstract removeClass(el: any, name: string): void
  abstract setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2): void
  abstract removeStyle(el: any, style: string, flags?: RendererStyleFlags2): void
  abstract setProperty(el: any, name: string, value: any): void
  abstract setValue(node: any, value: string): void
  abstract listen(target: any, eventName: string, callback: (event: any) => boolean | void): () => void
複製代碼

11.類計算屬性

@Component({
  selector: 'fa-input',
  template: `
    <i class="fa" [ngClass]="classes"></i>
  `,
  styleUrls: ['./fa-input.component.css']
})
export class FaInputComponent {
  @Input() icon: string;
	
  get  classes() {
    const cssClasses = {
      fa: true
    };
    cssClasses['fa-' + this.icon] = true;
    return cssClasses;
  }
}
複製代碼

12.元素綁定

  • @HostBinding()能夠爲指令的宿主元素添加類、樣式、屬性等,
  • @HostListener()能夠監聽宿主元素上的事件。
import { Directive, HostBinding, HostListener } from '@angular/core';

@Directive({
  selector: '[highLight]' # 定義指令
})
export class HighLightDirective{
  colors = [
    'hotpink', 'lightskyblue', 'goldenrod', 'peachpuff'
  ]; 
  @HostBinding('style.color') color: string;
  @HostBinding('style.borderColor') borderColor: string;  # 定義樣式
  @HostListener('keydown') onKeydown(){   # 定義監聽
    const color = Math.floor(Math.random() * this.colors.length);
    this.color = this.borderColor = this.colors[colorPick];
  }
}
複製代碼

13.viewChild

  • @ViewChild 選擇組件模板內的節點, 類型 ElementRef 或子組件
  • @ContentChild 選擇當前組件引用的子組件 @ContentChild(組件名)
  • 區別在於ViewChild選擇Shadow DOM, ContentChild 選擇 Light DOM,通常狀況下用ViewChild就ok了

14.元素寬度

  • element clientWidth

內聯元素以及沒有 CSS 樣式的元素的 clientWidth 屬性值爲 0。Element.clientWidth 屬性表示元素的內部寬度,以像素計。該屬性包括內邊距 padding,但不包括邊框 border、外邊距 margin 和垂直滾動條(若是有的話)。 當在根元素(元素)上使用clientWidth時(或者在上,若是文檔是在quirks(怪異)模式下),將返回viewport的寬度(不包括任何滾動條).node

  • jquery width()

始終指內容寬度,不包括borderjquery

width

15.scss 無效

# scss 文件
input {
 border: none;
 outline: none;
}
# 界面運行時css
input[_ngcontent-c0] {
 border: none;
 outline: none;
}
# 此時須要添加編譯處理
:host ::ng-deep input {
 border: none;
 outline: none;
}
複製代碼

參考文獻

相關文章
相關標籤/搜索