Angular学习笔记 常用指令

Posted by fsoooo Blog on July 8, 2021

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>&lt;app-sizer [(size)]="fontSizePx"&gt;&lt;/app-sizer&gt;
</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&lt;number&gt;();
//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 事件。

&lt;div&gt;
  &lt;button (click)="dec()" title="smaller"&gt;-&lt;/button&gt;
  &lt;button (click)="inc()" title="bigger"&gt;+&lt;/button&gt;
  &lt;label [style.font-size.px]="size"&gt;FontSize: px&lt;/label&gt;
&lt;/div&gt;
</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=&gt;view</code>:数据绑定,模板语法是 <code class="language-plaintext highlighter-rouge">[]</code></p>

<p><code class="language-plaintext highlighter-rouge">view=&gt;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>&lt;!--value是数据绑定,input是事件绑定--&gt;
&lt;input [value]="currentHero.name"  (input)="currentHero.name=$event.target.value"&gt;
&lt;!--等价--&gt;
&lt;input [(ngModel)]="currentHero.name"&gt;
</code></pre></div></div>

<table>
  <tbody>
    <tr>
      <td>![](https://upload-images.jianshu.io/upload_images/20187175-920dfe6318e845f1.png?imageMogr2/auto-orient/strip</td>
      <td>imageView2/2/w/766/format/webp)</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>![](https://upload-images.jianshu.io/upload_images/20187175-4dd8e83cfe860fc0.png?imageMogr2/auto-orient/strip</td>
      <td>imageView2/2/w/279/format/webp)</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 中寻找一个 &lt;mylist&gt; 标签,然后创建该组件,并插入此标签中。
//templateUrl - 组件 HTML 模板的地址。
//directives - 一个数组,包含 此 模板需要依赖的组件或指令。
//providers - 一个数组,包含组件所依赖的服务所需要的依赖注入提供者。

@Component({
   selector : 'mylist',
   template : '&lt;h2&gt;angular&lt;/h2&gt;'
   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 标签中显示组件值。
&lt;h3&gt;

&lt;img src=""&gt;
&lt;/h3&gt;
属性绑定: 把元素的属性设置为组件中属性的值。
&lt;img [src]="userImageUrl"&gt;
事件绑定: 在组件方法名被点击时触发。
&lt;button (click)="onSave()"&gt;保存&lt;/button&gt;
双向绑: 使用Angular里的NgModel指令可以更便捷的进行双向绑定。
&lt;input [value]="currentUser.firstName" (input)="currentUser.firstName=$event.target.value" &gt;
</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 列表中的每个项生成一个 &lt;li&gt; 标签。
//*ngIf 表示只有在选择的项存在时,才会包含 SiteDetail 组件。
&lt;li *ngFor="let site of sites"&gt;&lt;/li&gt;
&lt;site-detail *ngIf="selectedSite"&gt;&lt;/site-detail&gt;
</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>&lt;app-sizer [(size)]="fontSizePx"&gt;&lt;/app-sizer&gt;
</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&lt;number&gt;();
//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 事件。

&lt;div&gt;
  &lt;button (click)="dec()" title="smaller"&gt;-&lt;/button&gt;
  &lt;button (click)="inc()" title="bigger"&gt;+&lt;/button&gt;
  &lt;label [style.font-size.px]="size"&gt;FontSize: px&lt;/label&gt;
&lt;/div&gt;
</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=&gt;view</code>:数据绑定,模板语法是 <code class="language-plaintext highlighter-rouge">[]</code></p>

<p><code class="language-plaintext highlighter-rouge">view=&gt;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>&lt;!--value是数据绑定,input是事件绑定--&gt;
&lt;input [value]="currentHero.name"  (input)="currentHero.name=$event.target.value"&gt;
&lt;!--等价--&gt;
&lt;input [(ngModel)]="currentHero.name"&gt;
</code></pre></div></div>

<table>
  <tbody>
    <tr>
      <td>![](https://upload-images.jianshu.io/upload_images/20187175-920dfe6318e845f1.png?imageMogr2/auto-orient/strip</td>
      <td>imageView2/2/w/766/format/webp)</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>![](https://upload-images.jianshu.io/upload_images/20187175-4dd8e83cfe860fc0.png?imageMogr2/auto-orient/strip</td>
      <td>imageView2/2/w/279/format/webp)</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 中寻找一个 &lt;mylist&gt; 标签,然后创建该组件,并插入此标签中。
//templateUrl - 组件 HTML 模板的地址。
//directives - 一个数组,包含 此 模板需要依赖的组件或指令。
//providers - 一个数组,包含组件所依赖的服务所需要的依赖注入提供者。

@Component({
   selector : 'mylist',
   template : '&lt;h2&gt;angular&lt;/h2&gt;'
   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 标签中显示组件值。
&lt;h3&gt;

&lt;img src=""&gt;
&lt;/h3&gt;
属性绑定: 把元素的属性设置为组件中属性的值。
&lt;img [src]="userImageUrl"&gt;
事件绑定: 在组件方法名被点击时触发。
&lt;button (click)="onSave()"&gt;保存&lt;/button&gt;
双向绑: 使用Angular里的NgModel指令可以更便捷的进行双向绑定。
&lt;input [value]="currentUser.firstName" (input)="currentUser.firstName=$event.target.value" &gt;
</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 列表中的每个项生成一个 &lt;li&gt; 标签。
//*ngIf 表示只有在选择的项存在时,才会包含 SiteDetail 组件。
&lt;li *ngFor="let site of sites"&gt;&lt;/li&gt;
&lt;site-detail *ngIf="selectedSite"&gt;&lt;/site-detail&gt;
</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 对象实例。