angular11源码探索四[指令源码示例篇]

ng_class

父传子

set 的形式进行修改

<input type="range" [(ngModel)]="num" min="1" max="4">
<div appChColor [one]="num">
  hello world
</div>
@Directive({
  selector: '[appChColor]'
})
export class ChColorDirective {

  constructor(
    private el: ElementRef,
    private renderer: Renderer2
  ) {
    // this.changeColor('red')
  }
  // 设1,2,3,4对应三种不懂的颜色添加到
  obj={
    1:'#ccc',
    2:'#b41818',
    3:'#5e2caa',
    4:'#cb10ad'
  }
  @Input('one')
  set setValue(value) {
    this.renderer.setStyle(this.el.nativeElement,'color',this.obj[value])
  }

}

在查看NgClass 的时候竟然发现可以传set类型

type NgClassSupportedTypes = string[]|Set<string>|{[klass: string]: any}|null|undefined;

  public add1 = new Set();
  this.add1.add('aaa');
<div [ngClass]="add1">xxx</div>

实验了下,学习到了

let a = new Set('bbbaaabb bbbccc ddd  ccc ddd     aaaabcd');
console.log([...a]);
// [ 'b', 'a', ' ', 'c', 'd' ]

使用方法

 
    <some-element [ngClass]="'first second'">...</some-element>
 
      <some-element [ngClass]="['first', 'second']">...</some-element>
 
      <some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>

     <some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element>

    <some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
   <div  class="{{'bbb'}}">xxx</div>
	<div [class]="'foo'"></div>
	发现一个有趣的东西
    <div class="aaa bbb ccc" [class.aaa]="bool">xxxx</div>
	public bool=true;
	[class.aaa] 用于判断 class aaa 的是否存在

如果是字符串,清除空格变成数组

typeof value === 'string' ? value.split(/\s+/) : value;

我们发现是通过_renderer ,进行添加删除class

拿到DOM进行addClass,removeClass操作

 export class NgClass implements DoCheck {
     constructor(
      private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers,
      private _ngEl: ElementRef, private _renderer: Renderer2) {}
 }

 private _toggleClass(klass: string, enabled: boolean): void {
    klass = klass.trim();
    if (klass) {
      klass.split(/\s+/g).forEach(klass => {
        if (enabled) {
          this._renderer.addClass(this._ngEl.nativeElement, klass);
        } else {
          this._renderer.removeClass(this._ngEl.nativeElement, klass);
        }
      });
    }
  }

ngFor

<div *ngFor="let item of null">sss {{item}}</div>
我们发现这个dom不生成

<ul>
    <li *ngFor="let item of items as collection; index as i">	     	              {{i}}/{{collection.length}} - {{item}};
	</li>
</ul>
  items = ['a','b','c'];
视图
0/3 - a;
1/3 - b;
2/3 - c;

<span *ngFor ="let item of items; let i=index">{{i}}</span>
  • $implicit: T:可迭代(ngForOf)中各个项目的值。
  • ngForOf: NgIterable<T>:可迭代表达式的值。当表达式比属性访问更复杂时(例如,使用异步管道()时)很有用。userStreams | async
  • index: number:当前项目在iterable中的索引。
  • count: number:可迭代的长度。
  • first: boolean:当项目是可迭代的第一项时为true。
  • last: boolean:当项目是可迭代的最后一个项目时为true。
  • even: boolean:当项目的可迭代索引为偶数时为true。
  • odd: boolean:当项目在可迭代项中具有奇数索引时为true。

使用自定义模板

<ng-container *ngFor="let item of items; template: tpl"></ng-container>
<ng-template let-item let-i="index" #tpl>
    <p>{{i}}: {{item}};</p>
</ng-template>

  items = ['a','b','c'];

如果自定义模板为空就使用默认

<ng-container *ngFor="let item of items; template: null">
  <div>{{item}}</div>
</ng-container>

template 里面的内容为空的

简化版

<ng-template ngFor let-item [ngForOf]="items" let-i="index">
  <li>...</li>
</ng-template>

ngIf

运用于自定义模块,可以在页面展示内容
<ng-template [ngIf]="bool">xxxx</ng-template>

  public bool: boolean = true;
可以直接在值里面进行运算和输入函数
<div *ngIf="isBool()">bbbbb</div>

else 的正确使用

<span *ngIf="booleanCondition; else elseBlock">TRUE</span>
<ng-template #elseBlock>FALSE</ng-template>

判断支持模块
public booleanCondition=true

<span *ngIf="booleanCondition; then thenBlock; else elseBlock"></span>
<ng-template #thenBlock>THEN</ng-template>
<ng-template #elseBlock>ELSE</ng-template>

可以进行复杂的判断

<span *ngIf="booleanCondition;
            then nestedBooleanCondition ? tplRef : null;
            else nestedBooleanCondition ? elseRef : null"></span>
        <ng-template #tplRef>Template</ng-template>
        <ng-template #elseRef>Template</ng-template>
        
booleanCondition= true
nestedBooleanCondition= true

变通的形式
<span *ngIf="bool; else isBool? b1 : b2">TRUE</span>
<ng-template #b1>FALSE1</ng-template>
<ng-template #b2>FALSE2</ng-template>

bool=true;
isBool=true;

---------
<span *ngIf="bool; else elseBlock; let v">{{v}}</span>
<ng-template #elseBlock>FALSE1</ng-template>  
// v 展示的就是需要展示的变量
  public bool= 1;

ngPlural

添加删除DOM

// 变化是当个值得时候用 `=value`
<ul [ngPlural]="switchValue">
  <ng-template ngPluralCase="=0">
    <li>aaaaaaaaa.</li>
  </ng-template>
  <ng-template ngPluralCase="=1">
    <li>bbbbbbbbbbb.</li>
  </ng-template>
  <ng-template ngPluralCase="=sex">
    <li>xxxxxxxxxxxxx.</li>
  </ng-template>
</ul>

<button (click)="isPlural()">Click</button>

  public switchValue: number | string = 0;

  isPlural() {
    console.log(this.switchValue);
    if (this.switchValue === 0) {
      this.switchValue = 1;
    } else if (this.switchValue === 1) {
      this.switchValue = 'sex';
    } else if (this.switchValue === 'sex') {
      this.switchValue = 0;
    }
  }

===========
值 number

<ul [ngPlural]="switchValue">
  <ng-template ngPluralCase="0">
    <li>aaaaaaaaa.</li>
  </ng-template>
  <ng-template ngPluralCase="1">
    <li>bbbbbbbbbbb.</li>
  </ng-template>
<ul>
 
isPlural() {
    console.log(this.switchValue);
    if (this.switchValue === 0) {
      this.switchValue = 1;
    } else if (this.switchValue === 1) {
      this.switchValue = 0;
    }
  }

============
可以使用 `ng-container` 标签  
<ng-container [ngPlural]="switchValue">
  <ng-template ngPluralCase="0">
    aaaaaaaaa.
  </ng-template>
  <ng-template ngPluralCase="1">
    bbbbbbbbbbb.
   </ng-template>    
</ng-container>

=========
      如果[ngPlural]的值,找不到,就使用 other的内容
 <ng-template ngPluralCase="other"><li>我的默认内容</li></ng-template>      

源码中对这个做了解释

export function getPluralCategory(
    value: number, cases: string[], ngLocalization: NgLocalization, locale?: string): string {
  let key = `=${value}`;

  if (cases.indexOf(key) > -1) {
    return key;
  }

  key = ngLocalization.getPluralCategory(value, locale);

  if (cases.indexOf(key) > -1) {
    return key;
  }
 // 默认的使用
  if (cases.indexOf('other') > -1) {
    return 'other';
  }
// 报错了
  throw new Error(`No plural message found for value "${value}"`);
}

当时不理解,原来是做了国际化

export enum Plural {
  Zero = 0,
  One = 1,
  Two = 2,
  Few = 3,
  Many = 4,
  Other = 5,
}
  switch (plural) {
      case Plural.Zero:
        return 'zero';
      case Plural.One:
        return 'one';
      case Plural.Two:
        return 'two';
      case Plural.Few:
        return 'few';
      case Plural.Many:
        return 'many';
      default:
        return 'other';
    }

使用的时候

<ul [ngPlural]="switchValue">

  <ng-template ngPluralCase="one"> 
    <li>111111111111111</li>
  </ng-template>
  <ng-template ngPluralCase="few">
    <li>you have a few messages.</li>  
  </ng-template >
</ul>

switchValue=1 (one) 
		  =3  (few)

ngStyle

// .px   属性的写法,用于写尺寸
<div [ngStyle]="{backgroundColor:'red',width:'100px'}">xxxxxxxxx</div>
<div [ngStyle]="{'background-color':'red','width.px':100}">xxxxxxxxx</div>


ngSwitch

<ul [ngSwitch]="num1">
  <li *ngSwitchCase="num2">aaaaa</li>
  <li *ngSwitchCase="num3">bbbb</li>
  <!--默认-->
  <li *ngSwitchDefault>ccccc</li>
</ul>

  num1 = 1;
  num2 = 2;
  num3 = 3;
==============
<ul [ngSwitch]="'a'">
  <li *ngSwitchCase="'a'">aaaaa</li>
  <li *ngSwitchCase="'b'">bbbb</li>
  <!--默认-->
  <li *ngSwitchDefault>ccccc</li>
</ul>

==============
<ul [ngSwitch]="'a'">
  <li *ngSwitchCase="'a'">aaaaa
       <ng-container  [ngTemplateOutlet]="foo"></ng-container>
<!--       <span *ngSwitchDefault>默认内容1</span>-->
  </li>
  <li *ngSwitchCase="'b'">bbbb
    <ng-container [ngTemplateOutlet]="bar"></ng-container>
  </li>
  <!--默认-->
  <li *ngSwitchDefault>ccccc</li>
</ul>
<button (click)="isPlural()">Click</button>
<ng-template #foo>
  <span>Foo</span>
</ng-template>
<ng-template #bar>
  <span>Bar</span>
</ng-template>

========================

<ul [ngSwitch]="'b'">
  <li *ngSwitchCase="'a'"  [ngSwitch]="true">aaaaa
<!--    [ngSwitch] 就开始第二轮子判断-->
<!--    [ngSwitch]="true"  展示ng-container 的内容,  为false,展示默认的内容-->
       <ng-container *ngSwitchCase="true"  [ngTemplateOutlet]="foo"></ng-container>
       <span *ngSwitchDefault>默认内容1</span>
  </li>
  <li *ngSwitchCase="'b'"  [ngSwitch]="true">bbbb
    <ng-container *ngSwitchCase="true" [ngTemplateOutlet]="bar"></ng-container>
    <span *ngSwitchDefault>默认内容2</span>

  </li>
  <!--默认-->
  <li *ngSwitchDefault>ccccc</li>
</ul>

ngTemplate

<ng-container *ngTemplateOutlet="tap;"></ng-container>
<ng-template #tap>{{obj.sex}}</ng-template>
<!--  obj={sex:'bbb'}  -->
=============
<ng-template #tpl>foo</ng-template>
<div [ngTemplateOutlet]="tpl"></div>

==========
<ng-container *ngTemplateOutlet="tpl; context: obj"></ng-container>
// 设置一个变量等于这个属性
<ng-template let-foo="sex" #tpl>{{foo}}</ng-template>
  obj={sex:'bbb'}

===========
<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="{foo: values}"></ng-template>
<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>

  values=2;

==============
转化你容易看懂的模式
<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="obj"></ng-template>
<ng-template let-foo="sex" #tpl>{{foo}}</ng-template>

  obj={sex:'bbb'}

=============
<ng-template #testTemplate>test</ng-template>
<!--第一种-->
<ng-template [ngTemplateOutlet]="testTemplate"></ng-template>
<!--第二种-->
<ng-template *ngTemplateOutlet="testTemplate"></ng-template>


posted @ 2020-12-12 00:11  猫神甜辣酱  阅读(178)  评论(0编辑  收藏  举报