内容简介:从视图到数据源的单向绑定双向作为对比,
- 单向从数据源到视图
{{expression}}
[target]="expression"
bind-target="expression"
复制代码
从视图到数据源的单向绑定
(target)="statement" on-target="statement" 复制代码
双向
[(target)]="expression" bindon-target="expression" 复制代码
-
DOM property的值可以改变;HTML attribute的值不能改变。 在Angular的世界中,attribute唯一的作用是用来初始化元素和指令的状态。 当进行数据绑定时,只是在与元素和指令的property和事件打交道,而attribute就完全靠边站了。 -
如果忘了加方括号,
Angular会把这个表达式当做字符串常量看待,并用该字符串来初始化目标属性。 下面这个例子把HeroDetailComponent的prefix属性初始化为固定的字符串"1+1",而不是模板表达式"2"。Angular设置它,然后忘记它。
<app-hero-detail prefix="1+1" [hero]="currentHero"></app-hero-detail> 复制代码
作为对比, [hero]
绑定是组件的 currentHero
属性的活绑定,它会一直随着更新。
-
插值表达式 {{...}} ,先对双花括号中的表达式求值,再把求值的结果转换成字符串。
实际上,在渲染视图之前,
Angular把这些插值表达式翻译成了相应的属性绑定。 但数据类型不是字符串时,就必须使用属性绑定了。
<p><img src="{{heroImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="heroImageUrl"> is the <i>property bound</i> image.</p>
复制代码
-
不管是插值表达式还是属性绑定,都不会允许带有
script标签的HTML泄漏到浏览器中,二者都只渲染没有危害的内容。
src/app/app.component.ts
evilTitle = 'Template <script>alert("evil never sleeps")</script>Syntax';
src/app/app.component.html
<p><span>"{{evilTitle}}" is the <i>interpolated</i> evil title.</span></p>
<p>"<span [innerHTML]="evilTitle"></span>" is the <i>property bound</i> evil title.</p>
复制代码
-
attribute绑定 一般情况下,我们通过属性绑定来设置元素的属性property,而不用字符串设置元素的attribute。 考虑ARIA,SVG和table中的colspan/rowspan等attribute。 它们是纯粹的attribute,没有对应的属性可供绑定。 如果想写出类似下面这样的东西,就会暴露出痛点了:
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
复制代码
会得到这个错误:
Template parse errors: Can't bind to 'colspan' since it isn't a known native property
方括号中的部分不是元素的属性名,而是由 attr
前缀,一个点 (.) 和 attribute
的名字组成
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr> 复制代码
-
双向数据绑定
( [(...)] )想象盒子里的香蕉来记住方括号套圆括号[()]。 双向绑定语法实际上是属性绑定和事件绑定的语法糖。 -
内置属性型指令
-
a.通过绑定到
NgClass,可以同时添加或移除多个类。 把ngClass绑定到一个key:value形式的控制对象(value为boolean值)
src/app/app.component.html
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special</div>
src/app/app.component.ts
currentClasses: {};
setCurrentClasses() {
// CSS classes: added/removed per current state of component properties
this.currentClasses = {
'saveable': this.canSave,
'modified': !this.isUnchanged,
'special': this.isSpecial
};
}
复制代码
-
b.通过绑定
NgStyle设置多个内联样式。NgStyle需要绑定到一个key:value控制对象。
src/app/app.component.ts
currentStyles: {};
setCurrentStyles() {
// CSS styles: set per current state of component properties
this.currentStyles = {
'font-style': this.canSave ? 'italic' : 'normal',
'font-weight': !this.isUnchanged ? 'bold' : 'normal',
'font-size': this.isSpecial ? '24px' : '12px'
};
}
src/app/app.component.html
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
复制代码
-
模板输入变量:
hero前的let关键字创建了一个名叫hero的模板输入变量。 这个变量的范围被限制在所重复模板的单一实例上。事实上,你可以在其它内置结构型指令中使用同样的变量名。 模板引用变量:#phone的意思就是声明一个名叫phone的变量来引用<input>元素。
<input #phone placeholder="phone number"> 复制代码
模板引用变量的作用范围是整个模板。不要在同一个模板中多次定义同一个变量名,否则它在运行期间的值是无法确定的。
-
你总是可以在组件自己的模板中绑定到组件的公共属性,而不用管它们是否输入(
Input)属性或输出(Output)属性。 但Angular需要@Input()和@Output()装饰器来标记出那些允许被外部组件绑定到的属性。 声明输入与输出属性:
@Input() hero: Hero;
@Output() deleteRequest = new EventEmitter<Hero>();
复制代码
另外,还可以在指令元数据的 inputs
或 outputs
数组中标记出这些成员。比如这个例子:
@Component({
inputs: ['hero'],
outputs: ['deleteRequest'],
})
复制代码
-
json管道对调试绑定特别有用:
src/app/app.component.html (pipes-json)
<div>{{currentHero | json}}</div>
复制代码
它生成的输出是这样的:
{ "id": 0, "name": "Hercules", "emotion": "happy",
"birthdate": "1970-02-25T08:00:00.000Z",
"url": "http://www.imdb.com/title/tt0065832/",
"rate": 325 }
复制代码
- 构造函数在所有的生命周期钩子之前执行。
ngOnChanges()-》ngOnInit()-》ngDoCheck()-》ngAfterContentInit()-》ngAfterContentChecked()-》ngAfterViewInit()-》ngAfterViewChecked()-》ngOnDestroy()
-
rxjs知识
var subject = new Subject<string>();
subject.next(1);
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
//observerA: 1
复制代码
-
纯(
pure)管道与非纯(impure)管道: 默认情况下,管道都是纯的。Angular只有在它检测到输入值发生了纯变更时才会执行纯管道。 纯变更是指对原始类型值(String、Number、Boolean、Symbol)的更改,或者对对象引用(Date、Array、Function、Object)的更改。Angular会忽略对象内部的更改。 如果你更改了输入日期(Date)中的月份、往一个输入数组(Array)中添加新值或者更新了一个输入对象(Object)的属性,Angular都不会调用纯管道。Angular会在每个组件的变更检测周期中执行非纯管道。 非纯管道可能会被调用很多次,和每个按键或每次鼠标移动一样频繁。 -
ElementRef
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
复制代码
import
语句还从 Angular
的 core
库中导入了一个 ElementRef
符号。
你可以在指令的构造函数中注入 ElementRef
,来引用宿主 DOM
元素, ElementRef
(对视图中某个宿主元素的引用)通过其 nativeElement
属性给你了直接访问宿主 DOM
元素的能力。
注意:允许直接访问 DOM
会导致你的应用在 XSS
攻击前面更加脆弱。当需要直接访问
当需要直接访问 DOM
时,请把本 API
作为最后选择。优先使用 Angular
提供的模板和数据绑定机制。
或者你还可以看看 Renderer2
(实现自定义渲染器),它提供了可安全使用的 API
—— 即使环境没有提供直接访问原生元素的功能。
import { Directive, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef, private renderer: Renderer2) {
//el.nativeElement.style.backgroundColor = 'yellow';
this.renderer.setStyle(this.el.nativeElement, "backgroundColor", 'yellow');
}
}
复制代码
-
HostListener把一个事件绑定到一个宿主监听器,并提供配置元数据。
@HostListener('mousedown') onMouseEnter() {
this.highlight(this.highlightColor || this.defaultColor || 'red');
}
复制代码
mousedown
要监听的事件。
当 mousedown
事件发生时, Angular
就会执行所提供的处理器方法 onMouseEnter
-
你可以根据属性名在绑定中出现的位置来判定是否要加
@Input。 当它出现在等号右侧的模板表达式中时,它属于模板所在的组件,不需要@Input装饰器。 当它出现在等号左边的方括号([ ])中时,该属性属于其它组件或指令,它必须带有@Input装饰器。
<p [appHighlight]="color">Highlight me!</p> 复制代码
color
属性位于右侧的绑定表达式中,它属于模板所在的组件。 该模板和组件相互信任。因此 color
不需要 @Input
装饰器。 appHighlight
属性位于左侧,它引用了 HighlightDirective
中一个带别名的属性,它不是模板所属组件的一部分,因此存在信任问题。 所以,该属性必须带 @Input
装饰器。
-
bootstrap—— 根组件,Angular创建它并插入index.html宿主页面。 -
结构型指令中,星号(*)写法是个语法糖,
Angular会把它解开成一个<ng-template>标记,包裹着宿主元素及其子元素。Angular会在真正渲染的时候填充<ng-template>的内容,并且把<ng-template>替换为一个供诊断用的注释。
<ng-template let-hero="hero">
<div *ngIf="hero" [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>
复制代码
注意:如果没有使用结构型指令,而仅仅把一些别的元素包装进 <ng-template>
中,那些元素就是不可见的(被注释掉了)。
-
每个宿主元素上只能有一个结构型指令=》
*ngFor和*ngIf不能放在同一个宿主元素上。 有一个简单的解决方案:把*ngFor放在一个"容器"元素上,再包装进*ngIf元素。 这个元素可以使用ng-container,以免引入一个新的HTML层级。
<ul>
<ng-container *ngFor="let menu of menus">
<li *ngIf="!menu.children?.length">
</li>
</ng-container>
</ul>
复制代码
Angular
的 是一个分组元素,但它不会污染样式或元素布局,因为 Angular
压根不会把它放进 DOM
中。
template: <ng-template #toolbarTemplate [ngTemplateOutletContext]="{ $implicit: this}"></ng-template>
class: @ViewChild("toolbarTemplate") toolbarTemplate: TemplateRef<any>
简化写法:
<ng-template [ngTemplateOutlet]="toolbarTemplate || defaultToolbarTemplate"
[ngTemplateOutletContext]="{ $implicit: this}"></ng-template>
复制代码
-
表达式中的上下文变量是由模板引用变量
#aa、模板输入变量let bb和组件的成员cc叠加而成的。 那么优先级,模板输入变量>模板引用变量>指令的上下文变量>组件类的实例 -
模板表达式不能引用全局命名空间中的任何东西,比如
window和document。 它们也不能调用console.log或Math.max。它们只能引用表达式上下文中的内容。 -
声明式组件和入口组件: 声明式组件会在模板中通过组件声明的
selector(比如<cmb></cmb>)加载组件 入口组件entryComponents主要有3类: (1)在@NgModule中的bootstrap声明的根组件 (2)路由配置的组件 (3)动态组件 -
ngModule中的exports在模块a的ngModule中exports出一组组件、指令和管道-》模板b导入了模块a-》模块b下的所有组件的模板,都可以使用模块a的ngModule中exports出的组件、指令和管道 -
父子组件交互
<div class="seconds">{{timer.seconds}}</div>
<app-countdown-timer #timer></app-countdown-timer>
复制代码
这个本地变量方法是个简单便利的方法。但是它也有局限性,因为父组件-子组件的连接必须全部在父组件的 html
模板中进行。父组件本身的 ts
代码对子组件没有访问权。
当父组件类需要这种访问时,可以把子组件作为 ViewChild
,注入到父组件里面。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 工业大数据可视化面临的难点
- 结合实例浅析壳编写的流程与难点
- 微服务架构谈(八):拆分单体应用的难点
- OpenStack 学习有哪些难点?需要哪些知识储备?
- 知识图谱发展的难点&构建行业知识图谱的重要性
- 中间件(WAS、WMQ)运维 9个常见难点解析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
High Performance Python
Micha Gorelick、Ian Ozsvald / O'Reilly Media / 2014-9-10 / USD 39.99
If you're an experienced Python programmer, High Performance Python will guide you through the various routes of code optimization. You'll learn how to use smarter algorithms and leverage peripheral t......一起来看看 《High Performance Python》 这本书的介绍吧!