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>
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!