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;
}
复制代码

参考文献

相关文章
相关标签/搜索