NgIf
<div *ngIf="false"></div> <!-- never displayed -->
<div *ngIf="a > b"></div> <!-- displayed if a is more than b -->
<div *ngIf="str == 'yes'"></div> <!-- displayed if str holds the string "yes" -->
<div *ngIf="myFunc()"></div> <!-- displayed if myFunc returns a true value -->
NgSwitch
有时候需要根据不同的条件,渲染不同的元素,此时我们可以使用多个 ngIf
来实现。
<div class="container">
<div *ngIf="myVar == 'A'">Var is A</div>
<div *ngIf="myVar == 'B'">Var is B</div>
<div *ngIf="myVar != 'A' && myVar != 'B'">Var is something else</div>
</div>
如果 myVar
的可选值多了一个 'C'
,就得相应增加判断逻辑:
<div class="container">
<div *ngIf="myVar == 'A'">Var is A</div>
<div *ngIf="myVar == 'B'">Var is B</div>
<div *ngIf="myVar == 'C'">Var is C</div>
<div *ngIf="myVar != 'A' && myVar != 'B' && myVar != 'C'">
Var is something else
</div>
</div>
可以发现 Var is something else
的判断逻辑,会随着 myVar
可选值的新增,变得越来越复杂。遇到这种情景,我们可以使用 ngSwitch
指令。
<div class="container" [ngSwitch]="myVar">
<div *ngSwitchCase="'A'">Var is A</div>
<div *ngSwitchCase="'B'">Var is B</div>
<div *ngSwitchCase="'C'">Var is C</div>
<div *ngSwitchDefault>Var is something else</div>
</div>
NgStyle
NgStyle 让我们可以方便得通过 Angular 表达式,设置 DOM 元素的 CSS 属性。
- 设置元素的背景颜色
<div [style.background-color="'yellow'"]>
Use fixed yellow background
</div>
- 设置元素的字体大小
<!-- 支持单位: px | em | %-->
<div>
<span [ngStyle]="{color: 'red'}" [style.font-size.px]="fontSize">
red text
</span>
</div>
NgStyle 支持通过键值对的形式设置 DOM 元素的样式:
<div [ngStyle]="{color: 'white', 'background-color': 'blue'}">
Uses fixed white text on blue background
</div>
注意到 background-color
需要使用单引号,而 color
不需要。这其中的原因是,ng-style
要求的参数是一个 Javascript
对象,color
是一个有效的 key
,而 background-color
不是一个有效的 key
,所以需要添加 ''
。
NgClass
NgClass 接收一个对象字面量,对象的 key
是 CSS class 的名称,value
的值是 truthy/falsy
的值,表示是否应用该样式。
- CSS Class
.bordered {
border: 1px dashed black; background-color: #eee;
}
- HTML
<!-- Use boolean value -->
<div [ngClass]="{bordered: false}">This is never bordered</div>
<div [ngClass]="{bordered: true}">This is always bordered</div>
<!-- Use component instance property -->
<div [ngClass]="{bordered: isBordered}">
Using object literal. Border
</div>
<!-- Class names contains dashes -->
<div[ngClass]="{'bordered-box': false}">
Class names contains dashes must use single quote
</div>
<!-- Use a list of class names -->
<div class="base" [ngClass]="['blue', 'round']">
This will always have a blue background and round corners
</div>
NgFor
NgFor 指令用来根据集合(数组) ,创建 DOM
元素,类似于 ng1
中 ng-repeat
指令
<div class="ui list" *ngFor="let c of cities; let num = index">
<div class="item"> - </div>
</div>
使用 trackBy
提高列表的性能
@Component({
selector: 'my-app',
template: `
<ul>
<li *ngFor="let item of collection;trackBy: trackByFn"></li>
</ul>
<button (click)="getItems()">Refresh items</button>
`,
})
export class App {
constructor() {
this.collection = [{id: 1}, {id: 2}, {id: 3}];
}
getItems() {
this.collection = this.getItemsFromServer();
}
getItemsFromServer() {
return [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
}
trackByFn(index, item) {
return index; // or item.id
}
}
NgNonBindable
ngNonBindable 指令用于告诉 Angular 编译器,无需编译页面中某个特定的HTML代码片段。
<div class='ngNonBindableDemo'>
<span class="bordered"><!-- Image to hack wechat -->
<!-- <img src="/img/icon_wechat.png" width="0" height="0"> -->
<!-- <img src="/img/about-bg.jpg" width="0" height="0"> -->
<!-- Post Header -->
<style type="text/css">
header.intro-header{
position: relative;
background-image: url('/img/about-bg.jpg')
}
</style>
<header class="intro-header" >
<div class="header-mask"></div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<div class="post-heading">
<div class="tags">
</div>
<h1>Angular学习笔记 双向绑定</h1>
<h2 class="subheading"></h2>
<span class="meta">Posted by fsoooo Blog on July 7, 2021</span>
</div>
</div>
</div>
</div>
</header>
<!-- Post Content -->
<article>
<div class="container">
<div class="row">
<!-- Post Container -->
<div class="
col-lg-8 col-lg-offset-2
col-md-10 col-md-offset-1
post-container">
<p>Angular和Vue一样都是MVVM的框架,<code class="language-plaintext highlighter-rouge">MVVM</code>的核心机制就是<code class="language-plaintext highlighter-rouge">双向绑定</code>。</p>
<p>双向绑定将<code class="language-plaintext highlighter-rouge">属性绑定</code>与<code class="language-plaintext highlighter-rouge">事件绑定</code>结合在一起:</p>
<p><code class="language-plaintext highlighter-rouge">数据绑定</code>+<code class="language-plaintext highlighter-rouge">事件绑定</code>,模板语法是<code class="language-plaintext highlighter-rouge">[()]</code> <code class="language-plaintext highlighter-rouge">ngModule</code></p>
<p><code class="language-plaintext highlighter-rouge">变化检测</code>原理 –<code class="language-plaintext highlighter-rouge">脏检查</code></p>
<ul>
<li>属性绑定:设置特定的元素属性。</li>
<li>事件绑定:侦听元素更改事件。</li>
</ul>
<p>Angular 的<code class="language-plaintext highlighter-rouge">双向绑定语法</code>是<code class="language-plaintext highlighter-rouge">方括号</code>和<code class="language-plaintext highlighter-rouge">圆括号</code>的组合<code class="language-plaintext highlighter-rouge">[()]</code>。</p>
<p><code class="language-plaintext highlighter-rouge">[]</code> 进行<code class="language-plaintext highlighter-rouge">属性</code>绑定,<code class="language-plaintext highlighter-rouge">()</code>进行<code class="language-plaintext highlighter-rouge">事件</code>绑定</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><app-sizer [(size)]="fontSizePx"></app-sizer>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">@Input()</code> 输入</p>
<p><code class="language-plaintext highlighter-rouge">@Output()</code> 输出 。属性的名字必须遵循 <code class="language-plaintext highlighter-rouge">inputChange</code>模式,<code class="language-plaintext highlighter-rouge">input</code> 是相应<code class="language-plaintext highlighter-rouge">@Input()</code> 属性的名字</p>
<p>例如,如果 <code class="language-plaintext highlighter-rouge">@Input)()</code> 属性为 <code class="language-plaintext highlighter-rouge">size</code> ,则 <code class="language-plaintext highlighter-rouge">@Output()</code> 属性必须为 <code class="language-plaintext highlighter-rouge">sizeChange</code> 。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//src/app/sizer.component.ts
export class SizerComponent {
@Input() size: number | string;
@Output() sizeChange = new EventEmitter<number>();
//dec() 用于减小字体大小, inc() 用于增大字体大小。
dec() { this.resize(-1); }
inc() { this.resize(+1); }
// resize() 在最小/最大值的约束内更改 size 属性的值,并发出带有新 size 值的事件。
resize(delta: number) {
this.size = Math.min(40, Math.max(8, +this.size + delta));
this.sizeChange.emit(this.size);
}
}
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//src/app/sizer.component.html
inc() 和 dec() 这两个方法分别使用 +1 或 -1 调用 resize() 方法,它使用新的 size 值引发 sizeChange 事件。
<div>
<button (click)="dec()" title="smaller">-</button>
<button (click)="inc()" title="bigger">+</button>
<label [style.font-size.px]="size">FontSize: px</label>
</div>
</code></pre></div></div>
<p>官网:https://angular.cn/guide/two-way-binding</p>
<p>通过<code class="language-plaintext highlighter-rouge">$scope</code>对象把<code class="language-plaintext highlighter-rouge">数据模型</code>或<code class="language-plaintext highlighter-rouge">函数</code>行为<code class="language-plaintext highlighter-rouge">暴露</code>给<code class="language-plaintext highlighter-rouge">视图</code></p>
<p>使用<code class="language-plaintext highlighter-rouge">$watch</code>方法<code class="language-plaintext highlighter-rouge">监视</code>模型的<code class="language-plaintext highlighter-rouge">变化</code>,做出相应的动作</p>
<p><code class="language-plaintext highlighter-rouge">脏值检查</code>:对比数据是否有变更,来决定是否更新视图</p>
<p><code class="language-plaintext highlighter-rouge">angular</code>只有在<code class="language-plaintext highlighter-rouge">指定事件被触发时</code>进入<code class="language-plaintext highlighter-rouge">脏值检测</code>,大体如下:</p>
<ul>
<li>1.<code class="language-plaintext highlighter-rouge">DOM事件</code>,比如用户<code class="language-plaintext highlighter-rouge">输入文本</code>,<code class="language-plaintext highlighter-rouge">点击按钮</code>等。(<code class="language-plaintext highlighter-rouge">ng-click</code>)</li>
<li>2.<code class="language-plaintext highlighter-rouge">XHR</code>响应事件(<code class="language-plaintext highlighter-rouge">$http</code>)</li>
<li>3.浏览器<code class="language-plaintext highlighter-rouge">Location</code>变更(<code class="language-plaintext highlighter-rouge">$location</code>)</li>
<li>4.<code class="language-plaintext highlighter-rouge">Time</code>事件(<code class="language-plaintext highlighter-rouge">$timeout,$interval</code>)</li>
<li>5.执行<code class="language-plaintext highlighter-rouge">$digest()</code>或者<code class="language-plaintext highlighter-rouge">$apply()</code></li>
</ul>
<h3 id="双向绑定---ngmodel">双向绑定 - [(ngModel)]</h3>
<p><code class="language-plaintext highlighter-rouge">data=>view</code>:数据绑定,模板语法是 <code class="language-plaintext highlighter-rouge">[]</code></p>
<p><code class="language-plaintext highlighter-rouge">view=>data</code>:事件绑定,模板语法是<code class="language-plaintext highlighter-rouge">()</code></p>
<p><code class="language-plaintext highlighter-rouge">Angular</code>其实并没有一个双向绑定的实现,他的双向绑定就是<code class="language-plaintext highlighter-rouge">数据绑定+事件绑定</code>,模板语法是 <code class="language-plaintext highlighter-rouge">[()]</code>。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!--value是数据绑定,input是事件绑定-->
<input [value]="currentHero.name" (input)="currentHero.name=$event.target.value">
<!--等价-->
<input [(ngModel)]="currentHero.name">
</code></pre></div></div>
<table>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>主要入下集中情况可能改变数据:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>用户输入操作,比如点击,提交等。
请求服务端数据。
定时事件,比如setTimeout,setInterval。
</code></pre></div></div>
<p>变化检测原理 –<code class="language-plaintext highlighter-rouge">脏检查</code></p>
<p>所谓脏检查就是<code class="language-plaintext highlighter-rouge">存储所有变量的值</code>,每当可能有<code class="language-plaintext highlighter-rouge">变量发生变化</code>需要<code class="language-plaintext highlighter-rouge">检查</code>时,就将<code class="language-plaintext highlighter-rouge">所有变量的旧值</code>跟<code class="language-plaintext highlighter-rouge">新值</code>进行<code class="language-plaintext highlighter-rouge">比较</code>,<code class="language-plaintext highlighter-rouge">不相等</code>就说明检测到<code class="language-plaintext highlighter-rouge">变化</code>,需要<code class="language-plaintext highlighter-rouge">更新对应的视图</code>。</p>
<h3 id="angular-特性">angular 特性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MVC
模块化
自动化双向数据绑定
语义化标签、依赖注入等等
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">angularjs</code>的<code class="language-plaintext highlighter-rouge">双向数据绑定</code>采用<code class="language-plaintext highlighter-rouge">脏检查(dirty-checking)机制</code>。</p>
<p>ng只有在指定事件触发后,才进入 <code class="language-plaintext highlighter-rouge">$digest cycle</code> :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> - DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
- XHR响应事件 ( $http )
- 浏览器Location变更事件 ( $location )
- Timer事件( $timeout , $interval )
- 执行 $digest() 或 $apply()
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">Angular</code> 在 <code class="language-plaintext highlighter-rouge">scope 模型</code>上设置了一个<code class="language-plaintext highlighter-rouge">监听队列</code>,用来<code class="language-plaintext highlighter-rouge">监听数据变化</code>并更新 <code class="language-plaintext highlighter-rouge">view</code> 。</p>
<p>每次绑定一个东西到 <code class="language-plaintext highlighter-rouge">view</code>上时<code class="language-plaintext highlighter-rouge">AngularJS</code>就会往 <code class="language-plaintext highlighter-rouge">$watch 队列</code>里插入一条 <code class="language-plaintext highlighter-rouge">$watch</code>,用来检测它监视的 <code class="language-plaintext highlighter-rouge">model</code>里<code class="language-plaintext highlighter-rouge">是否有变化</code>的东西。</p>
<p>当<code class="language-plaintext highlighter-rouge">浏览器</code>接收到可以被 <code class="language-plaintext highlighter-rouge">angular context</code>处理的<code class="language-plaintext highlighter-rouge">事件</code>时,<code class="language-plaintext highlighter-rouge">$digest</code> 循环就会<code class="language-plaintext highlighter-rouge">触发</code>,<code class="language-plaintext highlighter-rouge">遍历</code>所有的 <code class="language-plaintext highlighter-rouge">$watch</code> ,最后更新<code class="language-plaintext highlighter-rouge">dom</code>。</p>
<h5 id="ng模块化编程">ng模块化编程</h5>
<p><code class="language-plaintext highlighter-rouge">Module.controller()</code>控制器</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>为应用中的模型设置初始状态,初始化$scope对象
通过$scope对象把数据模型或函数行为暴露给视图
使用$watch方法监视模型的变化,做出相应的动作
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">$scope</code>(上下文模型)作用域</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>视图和控制器之间的桥梁
用于在视图和控制器之间传递数据
利用$scope暴露数据模型(数据,行为)
</code></pre></div></div>
<p>单向绑定:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>模型变化过后,自动同步到界面上;
一般纯展示型的数据会用到单项数据绑定;使用表达式的方式都是单向的
</code></pre></div></div>
<p>双向绑定:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>两个方向的数据自动同步:
模型发生变化自动同步到视图上;
视图上的数据发生变化过后自动同步到模型上;
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">ng-app</code> 指令用于告诉 AngularJS 应用,当前这个元素是<code class="language-plaintext highlighter-rouge">根元素</code>。
<code class="language-plaintext highlighter-rouge">ng-controller</code> 指令用于为你的应用添加<code class="language-plaintext highlighter-rouge">控制器</code>。
<code class="language-plaintext highlighter-rouge">ng-model</code>指令用于建立<code class="language-plaintext highlighter-rouge">数据模型</code>
<code class="language-plaintext highlighter-rouge">Scope(作用域)</code>是应用在<code class="language-plaintext highlighter-rouge">HTML (视图)</code>和 <code class="language-plaintext highlighter-rouge">JavaScript (控制器)</code>之间的<code class="language-plaintext highlighter-rouge">纽带</code>。
用<code class="language-plaintext highlighter-rouge">双重大括号</code>来获取变量的值。当在控制器中添加<code class="language-plaintext highlighter-rouge">$scope</code>对象时,视图 <code class="language-plaintext highlighter-rouge">(HTML)</code>可以获取了这些属性。
<code class="language-plaintext highlighter-rouge">angular.module()</code>方法来<code class="language-plaintext highlighter-rouge">声明模块</code>。</p>
<p>Angular与Angularjs都采用<code class="language-plaintext highlighter-rouge">变化检测机制</code>,前者优于后者主要体现在:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>单项数据流动
以组件为单位维度独立进行检测
生产环境只进行一次检查
可自定义的变化检测策略:Default和onPush
可自定义的变化检测操作:markForcheck()、detectChanges()、detach()、reattach()、checkNoChanges()
代码实现上的优化,据说采用了VM friendly的代码。
</code></pre></div></div>
<table>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p><code class="language-plaintext highlighter-rouge">Angular 2</code> 应用程序应用主要由以下<code class="language-plaintext highlighter-rouge">8 个部分</code>组成:</p>
<p>1、模块 (<code class="language-plaintext highlighter-rouge">Modules</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>``NgModules``
`Angular 模块是一个带有 @NgModule 装饰器的类,它接收一个用来描述模块属性的元数据对象。`
</code></pre></div></div>
<p>2、组件 (<code class="language-plaintext highlighter-rouge">Components</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>从 @angular/core 中引入 Component 修饰器
建立一个普通的类,并用 @Component 修饰它
在 @Component 中,设置 selector 自定义标签,以及 template 模板
</code></pre></div></div>
<p>3、模板 (<code class="language-plaintext highlighter-rouge">Templates</code>)
<code class="language-plaintext highlighter-rouge">Angular模板的默认语言就是HTML</code></p>
<p>4、元数据 (<code class="language-plaintext highlighter-rouge">Metadata</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//元数据告诉 Angular 如何处理一个类。
//selector - 一个 css 选择器,它告诉 Angular 在 父级 HTML 中寻找一个 <mylist> 标签,然后创建该组件,并插入此标签中。
//templateUrl - 组件 HTML 模板的地址。
//directives - 一个数组,包含 此 模板需要依赖的组件或指令。
//providers - 一个数组,包含组件所依赖的服务所需要的依赖注入提供者。
@Component({
selector : 'mylist',
template : '<h2>angular</h2>'
directives : [ComponentDetails]
})
export class ListComponent{...}
</code></pre></div></div>
<p>5、数据绑定 (<code class="language-plaintext highlighter-rouge">Data Binding</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>插值 : 在 HTML 标签中显示组件值。
<h3>
<img src="">
</h3>
属性绑定: 把元素的属性设置为组件中属性的值。
<img [src]="userImageUrl">
事件绑定: 在组件方法名被点击时触发。
<button (click)="onSave()">保存</button>
双向绑: 使用Angular里的NgModel指令可以更便捷的进行双向绑定。
<input [value]="currentUser.firstName" (input)="currentUser.firstName=$event.target.value" >
</code></pre></div></div>
<p>6、指令 (<code class="language-plaintext highlighter-rouge">Directives</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//Angular模板是动态的 。当 Angular 渲染它们时,它会根据指令对 DOM 进行修改。
//*ngFor 告诉 Angular 为 sites 列表中的每个项生成一个 <li> 标签。
//*ngIf 表示只有在选择的项存在时,才会包含 SiteDetail 组件。
<li *ngFor="let site of sites"></li>
<site-detail *ngIf="selectedSite"></site-detail>
</code></pre></div></div>
<p>7、服务 (<code class="language-plaintext highlighter-rouge">Services</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//封装了某一特定功能,并且可以通过注入的方式供他人使用的独立模块
//把重复代码提取到服务中实现代码复用
export class Logger {
log(msg: any) { console.log(msg); }
error(msg: any) { console.error(msg); }
warn(msg: any) { console.warn(msg); }
}
</code></pre></div></div>
<p>8、依赖注入 (<code class="language-plaintext highlighter-rouge">Dependency Injection</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//查看构造函数的参数类型,来得知组件需要哪些服务
constructor(private service: SiteService) { }
</code></pre></div></div>
<p><img src="https://upload-images.jianshu.io/upload_images/6943526-6c43f35f3d868d12.gif?imageMogr2/auto-orient/strip" alt="" /></p>
<hr style="visibility: hidden;">
<ul class="pager">
<li class="previous">
<a href="/2021/07/06/Angular%E5%AD%A6%E4%B9%A0-Component%E4%B8%ADselector%E7%9A%84%E4%BD%BF%E7%94%A8/" data-toggle="tooltip" data-placement="top" title="Angular学习 Component中selector的使用">
Previous<br>
<span>Angular学习 Component中selector的使用</span>
</a>
</li>
<li class="next">
<a href="/2021/07/08/Angular%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E5%B8%B8%E7%94%A8%E6%8C%87%E4%BB%A4/" data-toggle="tooltip" data-placement="top" title="Angular学习笔记 常用指令">
Next<br>
<span>Angular学习笔记 常用指令</span>
</a>
</li>
</ul>
<!--Gitalk评论start -->
<!-- Gitalk end -->
</div>
<!-- Side Catalog Container -->
<!-- Sidebar Container -->
<div class="
col-lg-8 col-lg-offset-2
col-md-10 col-md-offset-1
sidebar-container">
<!-- Featured Tags -->
<section>
<hr class="hidden-sm hidden-xs">
<h5><a href="/tags/">FEATURED TAGS</a></h5>
<div class="tags">
<a href="/tags/#前端" title="前端" rel="13">
前端
</a>
<a href="/tags/#编程" title="编程" rel="28">
编程
</a>
<a href="/tags/#PHP" title="PHP" rel="25">
PHP
</a>
<a href="/tags/#Laravel" title="Laravel" rel="17">
Laravel
</a>
<a href="/tags/#Vue" title="Vue" rel="20">
Vue
</a>
<a href="/tags/#小程序" title="小程序" rel="24">
小程序
</a>
<a href="/tags/#生活" title="生活" rel="37">
生活
</a>
<a href="/tags/#随笔" title="随笔" rel="74">
随笔
</a>
<a href="/tags/#品格" title="品格" rel="25">
品格
</a>
<a href="/tags/#成长" title="成长" rel="13">
成长
</a>
<a href="/tags/#历史" title="历史" rel="14">
历史
</a>
<a href="/tags/#岁月" title="岁月" rel="16">
岁月
</a>
<a href="/tags/#读书" title="读书" rel="19">
读书
</a>
<a href="/tags/#情感" title="情感" rel="18">
情感
</a>
<a href="/tags/#亲情" title="亲情" rel="11">
亲情
</a>
<a href="/tags/#修行" title="修行" rel="53">
修行
</a>
</div>
</section>
<!-- Friends Blog -->
<hr>
<h5>FRIENDS</h5>
<ul class="list-inline">
<li><a href="https://www.jianshu.com/u/910c6f95a495">简书·fsoooo</a></li>
<li><a href="https://gitee.com/wangslei">码云·wangslei</a></li>
</ul>
</div>
</div>
</div>
</article>
<!-- async load function -->
<script>
function async(u, c) {
var d = document, t = 'script',
o = d.createElement(t),
s = d.getElementsByTagName(t)[0];
o.src = u;
if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
s.parentNode.insertBefore(o, s);
}
</script>
<!-- anchor-js, Doc:http://bryanbraun.github.io/anchorjs/ -->
<script>
async("//cdnjs.cloudflare.com/ajax/libs/anchor-js/1.1.1/anchor.min.js",function(){
// BY Fix:去除标题前的‘#’ issues:<https://github.com/qiubaiying/qiubaiying.github.io/issues/137>
// anchors.options = {
// visible: 'always',
// placement: 'right',
// icon: '#'
// };
anchors.add().remove('.intro-header h1').remove('.subheading').remove('.sidebar-container h5');
})
</script>
<style>
/* place left on bigger screen */
@media all and (min-width: 800px) {
.anchorjs-link{
position: absolute;
left: -0.75em;
font-size: 1.1em;
margin-top : -0.1em;
}
}
</style>
</span>
<span class="pre" ngNonBindable>
← This is what <!-- Image to hack wechat -->
<!-- <img src="/img/icon_wechat.png" width="0" height="0"> -->
<!-- <img src="/img/about-bg.jpg" width="0" height="0"> -->
<!-- Post Header -->
<style type="text/css">
header.intro-header{
position: relative;
background-image: url('/img/about-bg.jpg')
}
</style>
<header class="intro-header" >
<div class="header-mask"></div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<div class="post-heading">
<div class="tags">
</div>
<h1>Angular学习笔记 双向绑定</h1>
<h2 class="subheading"></h2>
<span class="meta">Posted by fsoooo Blog on July 7, 2021</span>
</div>
</div>
</div>
</div>
</header>
<!-- Post Content -->
<article>
<div class="container">
<div class="row">
<!-- Post Container -->
<div class="
col-lg-8 col-lg-offset-2
col-md-10 col-md-offset-1
post-container">
<p>Angular和Vue一样都是MVVM的框架,<code class="language-plaintext highlighter-rouge">MVVM</code>的核心机制就是<code class="language-plaintext highlighter-rouge">双向绑定</code>。</p>
<p>双向绑定将<code class="language-plaintext highlighter-rouge">属性绑定</code>与<code class="language-plaintext highlighter-rouge">事件绑定</code>结合在一起:</p>
<p><code class="language-plaintext highlighter-rouge">数据绑定</code>+<code class="language-plaintext highlighter-rouge">事件绑定</code>,模板语法是<code class="language-plaintext highlighter-rouge">[()]</code> <code class="language-plaintext highlighter-rouge">ngModule</code></p>
<p><code class="language-plaintext highlighter-rouge">变化检测</code>原理 –<code class="language-plaintext highlighter-rouge">脏检查</code></p>
<ul>
<li>属性绑定:设置特定的元素属性。</li>
<li>事件绑定:侦听元素更改事件。</li>
</ul>
<p>Angular 的<code class="language-plaintext highlighter-rouge">双向绑定语法</code>是<code class="language-plaintext highlighter-rouge">方括号</code>和<code class="language-plaintext highlighter-rouge">圆括号</code>的组合<code class="language-plaintext highlighter-rouge">[()]</code>。</p>
<p><code class="language-plaintext highlighter-rouge">[]</code> 进行<code class="language-plaintext highlighter-rouge">属性</code>绑定,<code class="language-plaintext highlighter-rouge">()</code>进行<code class="language-plaintext highlighter-rouge">事件</code>绑定</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><app-sizer [(size)]="fontSizePx"></app-sizer>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">@Input()</code> 输入</p>
<p><code class="language-plaintext highlighter-rouge">@Output()</code> 输出 。属性的名字必须遵循 <code class="language-plaintext highlighter-rouge">inputChange</code>模式,<code class="language-plaintext highlighter-rouge">input</code> 是相应<code class="language-plaintext highlighter-rouge">@Input()</code> 属性的名字</p>
<p>例如,如果 <code class="language-plaintext highlighter-rouge">@Input)()</code> 属性为 <code class="language-plaintext highlighter-rouge">size</code> ,则 <code class="language-plaintext highlighter-rouge">@Output()</code> 属性必须为 <code class="language-plaintext highlighter-rouge">sizeChange</code> 。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//src/app/sizer.component.ts
export class SizerComponent {
@Input() size: number | string;
@Output() sizeChange = new EventEmitter<number>();
//dec() 用于减小字体大小, inc() 用于增大字体大小。
dec() { this.resize(-1); }
inc() { this.resize(+1); }
// resize() 在最小/最大值的约束内更改 size 属性的值,并发出带有新 size 值的事件。
resize(delta: number) {
this.size = Math.min(40, Math.max(8, +this.size + delta));
this.sizeChange.emit(this.size);
}
}
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//src/app/sizer.component.html
inc() 和 dec() 这两个方法分别使用 +1 或 -1 调用 resize() 方法,它使用新的 size 值引发 sizeChange 事件。
<div>
<button (click)="dec()" title="smaller">-</button>
<button (click)="inc()" title="bigger">+</button>
<label [style.font-size.px]="size">FontSize: px</label>
</div>
</code></pre></div></div>
<p>官网:https://angular.cn/guide/two-way-binding</p>
<p>通过<code class="language-plaintext highlighter-rouge">$scope</code>对象把<code class="language-plaintext highlighter-rouge">数据模型</code>或<code class="language-plaintext highlighter-rouge">函数</code>行为<code class="language-plaintext highlighter-rouge">暴露</code>给<code class="language-plaintext highlighter-rouge">视图</code></p>
<p>使用<code class="language-plaintext highlighter-rouge">$watch</code>方法<code class="language-plaintext highlighter-rouge">监视</code>模型的<code class="language-plaintext highlighter-rouge">变化</code>,做出相应的动作</p>
<p><code class="language-plaintext highlighter-rouge">脏值检查</code>:对比数据是否有变更,来决定是否更新视图</p>
<p><code class="language-plaintext highlighter-rouge">angular</code>只有在<code class="language-plaintext highlighter-rouge">指定事件被触发时</code>进入<code class="language-plaintext highlighter-rouge">脏值检测</code>,大体如下:</p>
<ul>
<li>1.<code class="language-plaintext highlighter-rouge">DOM事件</code>,比如用户<code class="language-plaintext highlighter-rouge">输入文本</code>,<code class="language-plaintext highlighter-rouge">点击按钮</code>等。(<code class="language-plaintext highlighter-rouge">ng-click</code>)</li>
<li>2.<code class="language-plaintext highlighter-rouge">XHR</code>响应事件(<code class="language-plaintext highlighter-rouge">$http</code>)</li>
<li>3.浏览器<code class="language-plaintext highlighter-rouge">Location</code>变更(<code class="language-plaintext highlighter-rouge">$location</code>)</li>
<li>4.<code class="language-plaintext highlighter-rouge">Time</code>事件(<code class="language-plaintext highlighter-rouge">$timeout,$interval</code>)</li>
<li>5.执行<code class="language-plaintext highlighter-rouge">$digest()</code>或者<code class="language-plaintext highlighter-rouge">$apply()</code></li>
</ul>
<h3 id="双向绑定---ngmodel">双向绑定 - [(ngModel)]</h3>
<p><code class="language-plaintext highlighter-rouge">data=>view</code>:数据绑定,模板语法是 <code class="language-plaintext highlighter-rouge">[]</code></p>
<p><code class="language-plaintext highlighter-rouge">view=>data</code>:事件绑定,模板语法是<code class="language-plaintext highlighter-rouge">()</code></p>
<p><code class="language-plaintext highlighter-rouge">Angular</code>其实并没有一个双向绑定的实现,他的双向绑定就是<code class="language-plaintext highlighter-rouge">数据绑定+事件绑定</code>,模板语法是 <code class="language-plaintext highlighter-rouge">[()]</code>。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!--value是数据绑定,input是事件绑定-->
<input [value]="currentHero.name" (input)="currentHero.name=$event.target.value">
<!--等价-->
<input [(ngModel)]="currentHero.name">
</code></pre></div></div>
<table>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p>主要入下集中情况可能改变数据:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>用户输入操作,比如点击,提交等。
请求服务端数据。
定时事件,比如setTimeout,setInterval。
</code></pre></div></div>
<p>变化检测原理 –<code class="language-plaintext highlighter-rouge">脏检查</code></p>
<p>所谓脏检查就是<code class="language-plaintext highlighter-rouge">存储所有变量的值</code>,每当可能有<code class="language-plaintext highlighter-rouge">变量发生变化</code>需要<code class="language-plaintext highlighter-rouge">检查</code>时,就将<code class="language-plaintext highlighter-rouge">所有变量的旧值</code>跟<code class="language-plaintext highlighter-rouge">新值</code>进行<code class="language-plaintext highlighter-rouge">比较</code>,<code class="language-plaintext highlighter-rouge">不相等</code>就说明检测到<code class="language-plaintext highlighter-rouge">变化</code>,需要<code class="language-plaintext highlighter-rouge">更新对应的视图</code>。</p>
<h3 id="angular-特性">angular 特性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MVC
模块化
自动化双向数据绑定
语义化标签、依赖注入等等
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">angularjs</code>的<code class="language-plaintext highlighter-rouge">双向数据绑定</code>采用<code class="language-plaintext highlighter-rouge">脏检查(dirty-checking)机制</code>。</p>
<p>ng只有在指定事件触发后,才进入 <code class="language-plaintext highlighter-rouge">$digest cycle</code> :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> - DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
- XHR响应事件 ( $http )
- 浏览器Location变更事件 ( $location )
- Timer事件( $timeout , $interval )
- 执行 $digest() 或 $apply()
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">Angular</code> 在 <code class="language-plaintext highlighter-rouge">scope 模型</code>上设置了一个<code class="language-plaintext highlighter-rouge">监听队列</code>,用来<code class="language-plaintext highlighter-rouge">监听数据变化</code>并更新 <code class="language-plaintext highlighter-rouge">view</code> 。</p>
<p>每次绑定一个东西到 <code class="language-plaintext highlighter-rouge">view</code>上时<code class="language-plaintext highlighter-rouge">AngularJS</code>就会往 <code class="language-plaintext highlighter-rouge">$watch 队列</code>里插入一条 <code class="language-plaintext highlighter-rouge">$watch</code>,用来检测它监视的 <code class="language-plaintext highlighter-rouge">model</code>里<code class="language-plaintext highlighter-rouge">是否有变化</code>的东西。</p>
<p>当<code class="language-plaintext highlighter-rouge">浏览器</code>接收到可以被 <code class="language-plaintext highlighter-rouge">angular context</code>处理的<code class="language-plaintext highlighter-rouge">事件</code>时,<code class="language-plaintext highlighter-rouge">$digest</code> 循环就会<code class="language-plaintext highlighter-rouge">触发</code>,<code class="language-plaintext highlighter-rouge">遍历</code>所有的 <code class="language-plaintext highlighter-rouge">$watch</code> ,最后更新<code class="language-plaintext highlighter-rouge">dom</code>。</p>
<h5 id="ng模块化编程">ng模块化编程</h5>
<p><code class="language-plaintext highlighter-rouge">Module.controller()</code>控制器</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>为应用中的模型设置初始状态,初始化$scope对象
通过$scope对象把数据模型或函数行为暴露给视图
使用$watch方法监视模型的变化,做出相应的动作
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">$scope</code>(上下文模型)作用域</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>视图和控制器之间的桥梁
用于在视图和控制器之间传递数据
利用$scope暴露数据模型(数据,行为)
</code></pre></div></div>
<p>单向绑定:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>模型变化过后,自动同步到界面上;
一般纯展示型的数据会用到单项数据绑定;使用表达式的方式都是单向的
</code></pre></div></div>
<p>双向绑定:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>两个方向的数据自动同步:
模型发生变化自动同步到视图上;
视图上的数据发生变化过后自动同步到模型上;
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">ng-app</code> 指令用于告诉 AngularJS 应用,当前这个元素是<code class="language-plaintext highlighter-rouge">根元素</code>。
<code class="language-plaintext highlighter-rouge">ng-controller</code> 指令用于为你的应用添加<code class="language-plaintext highlighter-rouge">控制器</code>。
<code class="language-plaintext highlighter-rouge">ng-model</code>指令用于建立<code class="language-plaintext highlighter-rouge">数据模型</code>
<code class="language-plaintext highlighter-rouge">Scope(作用域)</code>是应用在<code class="language-plaintext highlighter-rouge">HTML (视图)</code>和 <code class="language-plaintext highlighter-rouge">JavaScript (控制器)</code>之间的<code class="language-plaintext highlighter-rouge">纽带</code>。
用<code class="language-plaintext highlighter-rouge">双重大括号</code>来获取变量的值。当在控制器中添加<code class="language-plaintext highlighter-rouge">$scope</code>对象时,视图 <code class="language-plaintext highlighter-rouge">(HTML)</code>可以获取了这些属性。
<code class="language-plaintext highlighter-rouge">angular.module()</code>方法来<code class="language-plaintext highlighter-rouge">声明模块</code>。</p>
<p>Angular与Angularjs都采用<code class="language-plaintext highlighter-rouge">变化检测机制</code>,前者优于后者主要体现在:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>单项数据流动
以组件为单位维度独立进行检测
生产环境只进行一次检查
可自定义的变化检测策略:Default和onPush
可自定义的变化检测操作:markForcheck()、detectChanges()、detach()、reattach()、checkNoChanges()
代码实现上的优化,据说采用了VM friendly的代码。
</code></pre></div></div>
<table>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p><code class="language-plaintext highlighter-rouge">Angular 2</code> 应用程序应用主要由以下<code class="language-plaintext highlighter-rouge">8 个部分</code>组成:</p>
<p>1、模块 (<code class="language-plaintext highlighter-rouge">Modules</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>``NgModules``
`Angular 模块是一个带有 @NgModule 装饰器的类,它接收一个用来描述模块属性的元数据对象。`
</code></pre></div></div>
<p>2、组件 (<code class="language-plaintext highlighter-rouge">Components</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>从 @angular/core 中引入 Component 修饰器
建立一个普通的类,并用 @Component 修饰它
在 @Component 中,设置 selector 自定义标签,以及 template 模板
</code></pre></div></div>
<p>3、模板 (<code class="language-plaintext highlighter-rouge">Templates</code>)
<code class="language-plaintext highlighter-rouge">Angular模板的默认语言就是HTML</code></p>
<p>4、元数据 (<code class="language-plaintext highlighter-rouge">Metadata</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//元数据告诉 Angular 如何处理一个类。
//selector - 一个 css 选择器,它告诉 Angular 在 父级 HTML 中寻找一个 <mylist> 标签,然后创建该组件,并插入此标签中。
//templateUrl - 组件 HTML 模板的地址。
//directives - 一个数组,包含 此 模板需要依赖的组件或指令。
//providers - 一个数组,包含组件所依赖的服务所需要的依赖注入提供者。
@Component({
selector : 'mylist',
template : '<h2>angular</h2>'
directives : [ComponentDetails]
})
export class ListComponent{...}
</code></pre></div></div>
<p>5、数据绑定 (<code class="language-plaintext highlighter-rouge">Data Binding</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>插值 : 在 HTML 标签中显示组件值。
<h3>
<img src="">
</h3>
属性绑定: 把元素的属性设置为组件中属性的值。
<img [src]="userImageUrl">
事件绑定: 在组件方法名被点击时触发。
<button (click)="onSave()">保存</button>
双向绑: 使用Angular里的NgModel指令可以更便捷的进行双向绑定。
<input [value]="currentUser.firstName" (input)="currentUser.firstName=$event.target.value" >
</code></pre></div></div>
<p>6、指令 (<code class="language-plaintext highlighter-rouge">Directives</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//Angular模板是动态的 。当 Angular 渲染它们时,它会根据指令对 DOM 进行修改。
//*ngFor 告诉 Angular 为 sites 列表中的每个项生成一个 <li> 标签。
//*ngIf 表示只有在选择的项存在时,才会包含 SiteDetail 组件。
<li *ngFor="let site of sites"></li>
<site-detail *ngIf="selectedSite"></site-detail>
</code></pre></div></div>
<p>7、服务 (<code class="language-plaintext highlighter-rouge">Services</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//封装了某一特定功能,并且可以通过注入的方式供他人使用的独立模块
//把重复代码提取到服务中实现代码复用
export class Logger {
log(msg: any) { console.log(msg); }
error(msg: any) { console.error(msg); }
warn(msg: any) { console.warn(msg); }
}
</code></pre></div></div>
<p>8、依赖注入 (<code class="language-plaintext highlighter-rouge">Dependency Injection</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//查看构造函数的参数类型,来得知组件需要哪些服务
constructor(private service: SiteService) { }
</code></pre></div></div>
<p><img src="https://upload-images.jianshu.io/upload_images/6943526-6c43f35f3d868d12.gif?imageMogr2/auto-orient/strip" alt="" /></p>
<hr style="visibility: hidden;">
<ul class="pager">
<li class="previous">
<a href="/2021/07/06/Angular%E5%AD%A6%E4%B9%A0-Component%E4%B8%ADselector%E7%9A%84%E4%BD%BF%E7%94%A8/" data-toggle="tooltip" data-placement="top" title="Angular学习 Component中selector的使用">
Previous<br>
<span>Angular学习 Component中selector的使用</span>
</a>
</li>
<li class="next">
<a href="/2021/07/08/Angular%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E5%B8%B8%E7%94%A8%E6%8C%87%E4%BB%A4/" data-toggle="tooltip" data-placement="top" title="Angular学习笔记 常用指令">
Next<br>
<span>Angular学习笔记 常用指令</span>
</a>
</li>
</ul>
<!--Gitalk评论start -->
<!-- Gitalk end -->
</div>
<!-- Side Catalog Container -->
<!-- Sidebar Container -->
<div class="
col-lg-8 col-lg-offset-2
col-md-10 col-md-offset-1
sidebar-container">
<!-- Featured Tags -->
<section>
<hr class="hidden-sm hidden-xs">
<h5><a href="/tags/">FEATURED TAGS</a></h5>
<div class="tags">
<a href="/tags/#前端" title="前端" rel="13">
前端
</a>
<a href="/tags/#编程" title="编程" rel="28">
编程
</a>
<a href="/tags/#PHP" title="PHP" rel="25">
PHP
</a>
<a href="/tags/#Laravel" title="Laravel" rel="17">
Laravel
</a>
<a href="/tags/#Vue" title="Vue" rel="20">
Vue
</a>
<a href="/tags/#小程序" title="小程序" rel="24">
小程序
</a>
<a href="/tags/#生活" title="生活" rel="37">
生活
</a>
<a href="/tags/#随笔" title="随笔" rel="74">
随笔
</a>
<a href="/tags/#品格" title="品格" rel="25">
品格
</a>
<a href="/tags/#成长" title="成长" rel="13">
成长
</a>
<a href="/tags/#历史" title="历史" rel="14">
历史
</a>
<a href="/tags/#岁月" title="岁月" rel="16">
岁月
</a>
<a href="/tags/#读书" title="读书" rel="19">
读书
</a>
<a href="/tags/#情感" title="情感" rel="18">
情感
</a>
<a href="/tags/#亲情" title="亲情" rel="11">
亲情
</a>
<a href="/tags/#修行" title="修行" rel="53">
修行
</a>
</div>
</section>
<!-- Friends Blog -->
<hr>
<h5>FRIENDS</h5>
<ul class="list-inline">
<li><a href="https://www.jianshu.com/u/910c6f95a495">简书·fsoooo</a></li>
<li><a href="https://gitee.com/wangslei">码云·wangslei</a></li>
</ul>
</div>
</div>
</div>
</article>
<!-- async load function -->
<script>
function async(u, c) {
var d = document, t = 'script',
o = d.createElement(t),
s = d.getElementsByTagName(t)[0];
o.src = u;
if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
s.parentNode.insertBefore(o, s);
}
</script>
<!-- anchor-js, Doc:http://bryanbraun.github.io/anchorjs/ -->
<script>
async("//cdnjs.cloudflare.com/ajax/libs/anchor-js/1.1.1/anchor.min.js",function(){
// BY Fix:去除标题前的‘#’ issues:<https://github.com/qiubaiying/qiubaiying.github.io/issues/137>
// anchors.options = {
// visible: 'always',
// placement: 'right',
// icon: '#'
// };
anchors.add().remove('.intro-header h1').remove('.subheading').remove('.sidebar-container h5');
})
</script>
<style>
/* place left on bigger screen */
@media all and (min-width: 800px) {
.anchorjs-link{
position: absolute;
left: -0.75em;
font-size: 1.1em;
margin-top : -0.1em;
}
}
</style>
rendered
</span>
</div>
Angular 4.x 新特性
If…Else Template Conditions
语法
<element *ngIf="[condition expression]; else [else template]"></element>
使用示例
<ng-template #hidden>
<p>You are not allowed to see our secret</p>
</ng-template>
<p *ngIf="shown; else hidden">
Our secret is being happy
</p>
<template>
—> <ng-template>
使用示例
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/delay';
@Component({
selector: 'exe-app',
template: `
<ng-template #fetching>
<p>Fetching...</p>
</ng-template>
<p *ngIf="auth | async; else fetching; let user">
</p>
`,
})
export class AppComponent implements OnInit {
auth: Observable<{}>;
ngOnInit() {
this.auth = Observable
.of({ username: 'semlinker', password: 'segmentfault' })
.delay(new Date(Date.now() + 2000));
}
}
使用 [hidden]
属性控制元素可见性存在的问题
<div [hidden]="!showGreeting">
Hello, there!
</div>
上面的代码在通常情况下,都能正常工作。但当在对应的 DOM 元素上设置 display: flex
属性时,尽管[hidden]
对应的表达式为 true
,但元素却能正常显示。对于这种特殊情况,则推荐使用 *ngIf
。
直接使用 DOM
API 获取页面上的元素存在的问题
@Component({
selector: 'my-comp',
template: `
<input type="text" />
<div> Some other content </div>
`
})
export class MyComp {
constructor(el: ElementRef) {
el.nativeElement.querySelector('input').focus();
}
}
以上的代码直接通过 querySelector()
获取页面中的元素,通常不推荐使用这种方式。更好的方案是使用 @ViewChild
和模板变量,具体示例如下:
@Component({
selector: 'my-comp',
template: `
<input #myInput type="text" />
<div> Some other content </div>
`
})
export class MyComp implements AfterViewInit {
@ViewChild('myInput') input: ElementRef;
constructor(private renderer: Renderer) {}
ngAfterViewInit() {
this.renderer.invokeElementMethod(
this.input.nativeElement, 'focus');
}
}
另外值得注意的是,@ViewChild()
属性装饰器,还支持设置返回对象的类型,具体使用方式如下:
@ViewChild('myInput') myInput1: ElementRef;
@ViewChild('myInput', {read: ViewContainerRef}) myInput2: ViewContainerRef;
若未设置 read
属性,则默认返回的是 ElementRef
对象实例。