Angular 2学习笔记——基础篇

Angular.cn

首先必须要给Angular.cn中文网点100个赞,与占着百度头条的angular2.axuer.com不同,它翻译了整个网站,而且当你点击某段文字的话,它会显示它的英文原版。

比如这样:

091827_MQ1o_2414359.png

Angular2网站的英文单词确实不好翻译,比如Tour of Heroes Tutorial(Angular2版的HelloWorld),你可以根据法语的规则翻译成英雄塔教程或者塔式英雄教程,而Angular.cn给了一个很酷炫的名字:《英雄指南》。

安装Angular2

官方推荐了2种方法使用Angular2,Quickstart和Quickstart CLI,前者是基础方式使用,后者是官方提供的脚手架,为了演示和学习的方便,我推荐大家都使用后者创建DEMO,我这里有两篇教程,分别讲解这两种使用方式。

Quickstart

Quickstart CLI

生命周期

我下意识的认为,只要一个语言或者框架有生命周期,那么它一定是最重要的,牢记它可能不能马上对你有帮助,但肯定对你未来的编程生涯大有裨益。

093212_XDS2_2414359.png

这里有一段官方的对生命周期目的及意义的解释,我们可以根据自己的理解来揣摩一下这段文字的意义。

原链接:生命周期

钩子

目的和时机

ngOnChanges

当Angular(重新)设置数据绑定输入属性时响应。 该方法接受当前和上一属性值的SimpleChanges对象

当被绑定的输入属性的值发生变化时调用,首次调用一定会发生在ngOnInit之前。

ngOnInit

在Angular第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。

在第一轮ngOnChanges完成之后调用,只调用一次

ngDoCheck

检测,并在发生Angular无法或不愿意自己检测的变化时作出反应。

在每个Angular变更检测周期中调用,ngOnChangesngOnInit之后。

ngAfterContentInit

当把内容投影进组件之后调用。

第一次NgDoCheck之后调用,只调用一次。

只适用于组件

ngAfterContentChecked

每次完成被投影组件内容的变更检测之后调用。

ngAfterContentInit和每次NgDoCheck之后调用

只适合组件

ngAfterViewInit

初始化完组件视图及其子视图之后调用。

第一次ngAfterContentChecked之后调用,只调用一次。

只适合组件

ngAfterViewChecked

每次做完组件视图和子视图的变更检测之后调用。

ngAfterViewInit和每次ngAfterContentChecked之后调用。

只适合组件

ngOnDestroy

当Angular每次销毁指令/组件之前调用并清扫。 在这儿反订阅可观察对象和分离事件处理器,以防内存泄漏。

在Angular销毁指令/组件之前调用。

使用Angular2

1、插值/模板表达式

插值表达式跟Angular1没什么区别——双大括号包裹数据,Vue也支持这个,值不过Vue叫“声明式渲染”或者“mustache”。

{{title}}
<!--app works-->

与此同时,插值表达式也支持简单的JavaScript运算,这种方法叫做模板表达式,在app.component.ts里赋值两个变量data1和data2。

//app.component.ts
export class AppComponent {
  data1 = "hello";
  data2 = "world";
}

修改app.component.html,它就会展示我们输入的值

{{data1+data2}}
<!--helloworld-->

值得一提的是模板表达式并不支持所有的JavaScript运算,比如。

  • 赋值 (=+=-=, ...)

  • new运算符

  • 使用;,的链式表达式

  • 自增或自减操作符 (++--)

2、绑定语法

用过Angular 1的肯定对ng-model语句印象深刻,这种绑定语法省去了原来JavaScript程序员编写的一大段关于DOM操作的代码,Vue中也有自己的绑定语法语句v-model,而这种优势在Angular 2中也有所体现,我们先来看一段关于数据绑定方向的说明。

数据方向

语法

单向

从数据源到视图目标

{{expression}}//插值表达式
[target] = "expression"//Property、Attribute
bind-target = "expression"//类、样式

单向

从视图目标到数据源

(target) = "statement"
on-target = "statement"

双向

[(target)] = "expression"
bindon-target = "expression"

注:中括号“[]”或者小括号“()”包裹目标“target”的方法是简写形式,“bind-”、“on-”、“bindon-”这种写法是规范形式,不论你使用哪种形式,都能够达到你的目的。

2.1 从数据源到视图目标

我们还是看小例子,我们在app.component.html里放两个p标签,然后绑定它的类名。

<!--app.component.html-->
<p [class]="redText">如果显示绿色就正常了</p>
<p bind-class="redText">如果显示绿色就正常了</p>

然后我们在app.component.css里写上它的样式。

/*app.component.css*/
.redText{ color: red }
.greenText{ color: green }

最后我们在app.component.ts里写上我们要绑定的数据。

//app.component.ts
export class AppComponent {
  redText = "greenText";
}

走你┏ (゜ω゜)=☞

094232_srnO_2414359.png

OK,没有问题,我们看到,本来我们在页面里给p标签绑定的类名指定它为红色,但是我们在数据源把它改成了绿色,于是它就像我们期望的那样显示成了绿色。

此外,从数据源到视图目标的方法,不光可以绑定类名,还可以绑定属性或者样式,比如。

<!--Property-->
<img [src] = "heroImageUrl">
<hero-detail [hero]="currentHero"></hero-detail>
<div [ngClass] = "{selected: isSelected}"></div>
<!--Attribute-->
<button [attr.aria-label]="help">help</button>
<!--CSS 类-->
<div [class.special]="isSpecial">Special</div>
<!--样式-->
<button [style.color] = "isSpecial ? 'red' : 'green'">

这种绑定方法作用极大,我们今后的也会频繁用到这些。

2.2 从视图目标到数据源

从视图目标到数据源的绑定实际上就是“事件”,官方划分了三种:元素事件、组件事件、指令事件。

<!--元素的事件-->
<button (click) = "onSave()">Save</button>
<!--组件的事件-->
<hero-detail (deleteRequest)="deleteHero()"></hero-detail>
<!--指令的事件-->
<div (myClick)="clicked=$event">click me</div>

原理上大同小异,比如元素事件,其实就是你绑定了“click”方法,但是数据源并不知道你绑它干什么,这时候视图目标就告诉数据源:“你给我执行onSave()方法”,这就是视图目标到数据源的绑定。

2.3 双向

话不多说,小栗子。

<!--app.component.html-->
<p>{{ data }}</p>
<input type="text" [(ngModel)]="data">

当我们在input框里输入任何文字,都会在上方的p标签内显示。对于学过Angular 1 和Vue的人来说这个栗子实在太熟悉了,因为它们两者也有着一模一样的用法,Angular 1使用的是ng-model,Vue使用的是v-model,写法不同,但作用相同。

3、条件与循环

3.1 条件

Angular 1里有ng-if,Vue里有v-if,我们的Angular 2的语法是*ngIf。

注:“ngIf”前面的“*”是一种语法糖,有点类似于jQuery里面的“$”。

它的具体用法就是,根据*ngIf里面的值来判断当前标签是否显示,为了理解,我们将实现下面这个例子:当我们点击按钮时,上方的p标签将消失。

<!--app.component.html-->
<p *ngIf="show">hello world</p>
<button (click)="hide()">点击消失</button>
//app.component.ts
export class AppComponent {
  show = true;
  hide(): void{
    this.show = false;
  }
}

上一节我们已经讲到,通过绑定事件的方法我们给button按钮绑定了click事件——它将执行hide()函数,hide()函数将show的值改为了false,所以p标签就消失了。

注:这个函数的写法与我们学过的Javascript写法有些出入,冒号“:”前面是函数名字和括号,括号内可以写形参,冒号后面是函数的返回值类型,这种写法是ES6的写法,关于ES6的更多介绍可以点击传送门:ECMAScript 6 入门,由于后面我们还要用到很多ES6的相关语法知识,所以尽早阅读对你的学习肯定事半功倍。

OK,没有问题,这个栗子很简单,没什么难的,关于“条件”显示语法,Angular 2还提供了一个与众不同的语法——*ngSwitch,学过Javascript或者后台语言的应该对这个语法用法猜一个大概。

<span [ngSwitch]="toeChoice">
  <span *ngSwitchCase="'Eenie'">Eenie</span>
  <span *ngSwitchCase="'Meanie'">Meanie</span>
  <span *ngSwitchCase="'Miney'">Miney</span>
  <span *ngSwitchCase="'Moe'">Moe</span>
  <span *ngSwitchDefault>other</span>
</span>

数据源可以对toeChoice赋值,视图目标根据数据源提供的值来对页面进行渲染,想一想这种用法可以用在哪里呢?比如说我们要写一个后台管理系统,系统可以根据登录用户的身份不同来分别渲染页面,我认为这种可以全局控制的方法实在很酷,避免了我们写一大堆*ngIf。

值得一提的是,可见性与条件语法完全是两个概念,当元素的display设置为none,或者visibility设置为hidden的时候,不可见的元素仍然在DOM当中占据着位置,系统还有可能会花费很大的内存去检查更新它,而使用条件语法,则会彻底的将元素从DOM当中删除,节省了内存,提高了系统性能。

3.2 循环

还是原来的配方,还是原来的味道,Angular 1里有ng-repeat,Vue里有v-for,我们的Angular 2的语法是*ngFor。

这次的栗子我们打算写一个类。

//app.component.ts
class Student {
  id: number;
  name: String;
}

然后在导出类AppComponent里初始化一下。

//app.component.ts
export class AppComponent {
  ClassTwoStudents: Student[] = [
    {
      id: 1,
      name: "张三"
    },
    {
      id: 2,
      name: "李四"
    },
    {
      id: 3,
      name: "王五"
    },
  ]
}

现在2班学生里有3个人,分别是张三、李四、王五,然后是页面。

<!--app.component.html-->
<ul>
    <li *ngFor="let student of ClassTwoStudents">
        <span>{{ student.id }}</span>
        <span>{{ student.name }}</span>
    </li>
</ul>

注意,这里的语法一定是let student of ClassTwoStudents,写错、或者缺少了任何一个,并且没有很好的调试工具的情况下,这可能是一个非常难以发现的错误。

115736_duCn_2414359.png

渲染结果如上图,OK,没有问题。

现在我们想追加一个问题,如何获得这个列表的索引值呢?很简单,只要在*ngFor里加上“let i = index;”就可以了。

<!--app.component.html-->
<ul>
    <li *ngFor="let student of ClassTwoStudents;let i=index;">
        <span>{{ student.id }}</span>
        <span>{{ student.name }}</span>
        <input type="button" (click)="showIndex(i)">     
    </li>
</ul>

我们增加了一个按钮,点击按钮显示索引值。现在我们把逻辑部分补全。

show(idx): void {
    console.log(idx)
}

现在我们点击按钮,可以显示他们相应的索引值了,除了index索引值之外,Angular还内置了首元素、尾元素、奇元素、偶元素,但是很遗憾,我们并不能直接对它们进行操作,他们仅用于判断并返回相应的布尔值。为了能清楚的显示结果,我们把我们的列表改成表格。

<!--app.component.html-->
<table>
    <tr>
        <th>学生id</th>
        <th>学生姓名</th>
        <th>索引值</th>
        <th>是否为首元素</th>
        <th>是否为尾元素</th>
        <th>是否为偶元素</th>
        <th>是否奇元素</th>
    </tr>
    <tr *ngFor="let student of ClassTwoStudents;
    let i = index;
    let first = first;
    let last = last;
    let even = even;
    let odd = odd;"
    >
        <td>{{ student.id }}</td>
        <td>{{ student.name }}</td>
        <td>{{ i }}</td>
        <td>{{ first }}</td>
        <td>{{ last }}</td>
        <td>{{ even }}</td>
        <td>{{ odd }}</td>
    </tr>
</table>

显示结果如下。

151543_ECrL_2414359.png

因此,假如我们想对它们进行操作的话,只能对整个表格进行遍历,然后判断结果为true的时候再进行操作。

4、其他内置指令

4.1 类绑定

4.1.1 单个类绑定

我们有两种方法绑定单一类,一种是第2.1节提到的数据绑定,另一种是通过以下语法。

<!-- toggle the "special" class on/off with a property -->
<div [class.special]="isSpecial">The class binding is special</div>

<!-- binding to `class.special` trumps the class attribute -->
<div class="special"
     [class.special]="!isSpecial">This one is not so special</div>

当isSpecial为true时,special类就被自动添加到class里,而!isSpecial的值就为false,special类就不会被添加到class里。

4.1.2 多个类的绑定

在工作当中,只添加一个类往往不能满足客户的需求,客户希望可以添加多个类,于是,客户提供给我们一段文字,他希望可以自由的添加样式。

<!--app.component.html-->
粗体:<input type="checkbox" value="粗体" [checked]="isBold" (change)="bold()">
变红:<input type="checkbox" value="变红" [checked]="isRed" (change)="red()">
下划线:<input type="checkbox" value="下划线" [checked]="isUnderLine" (change)="underline()">
<div [ngClass]="chooseClasses">我就是一段文字</div>
<button (click)="setClasses()">点击切换样式</button>

由于Angular 2不能直接绑定check事件,所以我们改用绑定change事件来代替它(此处先挖一个坑,如果后续学习过程中有更简便的方法再回来更新,如果有谁看到这个文章,并且有更好的建议,也可以邮件联系我13920422663@163.com)

//app.component.ts
chooseClasses: {};
  
  isBold: boolean;
  isRed: boolean;
  isUnderLine: boolean;
  
  bold(): void{
    if(this.isBold==true){
      this.isBold = false;
    }else{
      this.isBold = true;
    }
  }
  red(): void{
   if(this.isRed==true){
     this.isRed = false;
   }else{
     this.isRed = true;
   }
 }
  underline(): void{
    if(this.isUnderLine==true){
      this.isUnderLine = false;
    }else{
      this.isUnderLine = true;
    }
  }

  setClasses() {
    this.chooseClasses =  {
      bold: this.isBold,
      red: this.isRed,
      underline: this.isUnderLine
    };
  }

我们需要声明在html代码中绑定的chooseClasses这个对象,然后补充setClasses这个方法,把所需要的类名添加进来就可以了,当this.isBold、this.isRed、this.isUnderLine为true时,这些类名就会相应的添加到ngClass这个位置。

最后别忘了把样式补充上。

/*app.component.css*/
.red{ color: red }
.bold{ font-weight: bold }
.underline{ text-decoration: underline }

运行。

122417_1h0p_2414359.png

我们可以使用谷歌浏览器的查看元素功能,看到类名已经添加进来了。

122533_DfvW_2414359.png

4.2 样式绑定

上节中,我们通过类绑定,修改的文字的样式,其实Angular 2提供了专门的样式绑定语句——style.style-name,我个人极不推荐将样式直接写在html代码上,这样不仅破坏了语义化原则,也不符合MVC模型,而且代码的可读性很差,把所有CSS样式写在专门的CSS文件里,或者使用less或者mass预编译,是我个人更推荐的方式。

尽管有如此多的弊端,但官方给我们提供了这种方式,为了教程的完整性,我还是决定讲一讲,好在样式绑定和类绑定的用法大同小异。

和类绑定一样,样式绑定也分单一样式绑定和多个样式绑定,这里我就不分开讲了,我们对比代码来看。

4.2.1 单一样式绑定
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'" >
  This div is x-large.
</div>
4.2.2 多个样式绑定
currentStyles: {};
setCurrentStyles() {
  this.currentStyles = {
    // CSS styles: set per current state of component properties
    'font-style':  this.canSave      ? 'italic' : 'normal',
    'font-weight': !this.isUnchanged ? 'bold'   : 'normal',
    'font-size':   this.isSpecial    ? '24px'   : '12px'
  };
}

都是通过布尔值来判断是否添加样式。

5、表单

表单在前端工程师的开发过程当中实在是太重要了,表单中包含大量的属性的事件,应当是我们学习的重中之重,然而官方在开发指南里的表单讲解过于简单,超过一半的篇幅实际是在讲绑定语法,这我决定按照标签分类来讲解。

5.1 模板引用变量(template reference variable)

官方取名为“变量”,我更倾向于将它理解为“万能钥匙”,写法是"#"或者“ref-”加变量,只要将它写在表单内的任何标签,就可以获取它的属性。

//app.component.html
<input type="text" #f value="beef" name="food" [(ngModel)]="myFood">
<p>input type: {{ f.type }}</p>
<p>input value: {{ f.value }}</p>
<p>input name: {{ f.name }}</p>

输出结果。

102140_AG4X_2414359.png

在监听input的value属性时,与ngModel一样,可以监听用户的实时输入信息,此外,它还能绑定在radio(单选按钮)或者checkbox(多选按钮),监听它们的checked属性,来判断该按钮是否被选中了,非常方便。

5.2 下拉框

在这一节中,我们该死的客户又回来了,他提出了他的需求,希望我们在一个表单当中写三个下拉框,并获取他们值。

首先说下思路。

  1. 将“ngForm”赋值给一个模板引用变量
  2. 在select标签写上ngModel
  3. 在option标签绑定ngValue,并把select标签的name值赋给它

接下来我们可以直接看代码。

import {Component} from '@angular/core';
@Component({
  selector: 'example-app',
  template: `
    <form #f="ngForm">
      <select name="state1" ngModel>
        <option value="" disabled>Choose a state1</option>
        <option *ngFor="let state1 of states" [ngValue]="state1">
          {{ state1.abbrev }}
        </option>
      </select>
      <select name="state2" ngModel>
        <option value="" disabled>Choose a state2</option>
        <option *ngFor="let state2 of states" [ngValue]="state2">
          {{ state2.abbrev }}
        </option>
      </select>
      <select name="state3" ngModel>
        <option value="" disabled>Choose a state3</option>
        <option *ngFor="let state3 of states" [ngValue]="state3">
          {{ state3.abbrev }}
        </option>
      </select>
    </form>
     <p>Form value: {{ f.value | json }}</p>
     <!-- example value: {state: {name: 'New York', abbrev: 'NY'} } -->
  `,
})
export class SelectControlComp {
  states = [
    {name: 'Arizona', abbrev: 'AZ'},
    {name: 'California', abbrev: 'CA'},
    {name: 'Colorado', abbrev: 'CO'},
    {name: 'New York', abbrev: 'NY'},
    {name: 'Pennsylvania', abbrev: 'PA'},
  ];
}

输出结果。

104633_iEkS_2414359.png

OK,没有问题,如果我们想取state2的name值,直接写上f.value.state2.name就可取到。

除了这种用法,官方还提供了使用FormControll和FormGroup进行取值,因为这两个模块涉及到面向对象的知识,在这里我先挖一个坑,这将在Angular 2学习笔记——高级篇中讲解。

5.3 input框

运用数据绑定知识和模板引用变量知识已经足够让我们对各种input框的数据做大部分的操作了,我们本节要讨论的是input框的状态

状态

为真时的 CSS 类

为假时的 CSS 类

控件已经被访问过

ng-touched

ng-untouched

控件值已经变化

ng-dirty

ng-pristine

控件值是有效的

ng-valid

ng-invalid

Angular 2系统会根据状态,为控件添加上相应的类名,理论上,这种机制可以应用到表单内的任何控件内,但是我们绝大多数会把它用在input框(type=text)。

首先我们来看一段代码。

<!--app.component.html-->
<input type="text" class="" id="name"
  required
  [(ngModel)]="test"
  #spy>
<br>input框的类名有: {{spy.className}}

要使用它,必须在input框绑定ngModel属性,然后我们随便给它赋一个初值test=“测试”,为了演示ng-invalid,我们还加上required属性(必须有值)。

114018_FSnF_2414359.png

我们并没有给class加上任何一个类名,系统为我们自动添加了三个类名,下面我们可以进行测试。

  1. 当我们的input框第一次获得焦点,并且失去焦点时,ng-untouched变为了ng-touched
  2. 当我们修改input框内的值时,ng-pristine变成了ng-dirty
  3. 当我们将内容全部删去时,ng-valid变成了ng-invalid

所以,根据系统给我们提供的这些类名,我们可以编写相应的样式,比如给ng-invalid加上一些红色背景之类的。

5.4 使用ngSubmit提交表单

<!--app.component.html-->
<form (ngSubmit)="test()" #heroForm="ngForm">
    <input type="text" class="" id="name"
    required
    [(ngModel)]="test"
    #spy>
    <button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
</form>

我们把上一节的input框加入了一个form表单中,出人意料的是系统居然报错了,原来系统告诉你如果你的input框想放在一个form表单里,并且还绑定了ngModel,那么它就必须包含name属性,我们把name属性加上,系统错误就消失了。

表单提交函数并没有采用onSubmit(),我强烈建议自己编写提交函数,这样表单当中出现的错误信息在前台就可以检测到,并且更友善的提示用户修改,这样做可以大大提供系统运行的效率。

表单提交函数之外还绑定了一个模板引用变量,初值是“ngForm”,这个初值指的是整个表单,是系统自动为我们的form标签分配的,所以,当我们绑定了submit按钮的disabled属性值,值是false的情况下,用户是无法点击提交的。

6、管道

7、使用HTTP通信

8、动画

由于动画模块没有包含在我们的《英雄指南》里,所以Angular 2官网上的的动画模块描述的十分模糊,我们没有办法通过像操作《英雄指南》那样直接Ctrl+C/V的操作直接展示出效果,不过万幸的事,你还在坚持读我这篇博文,我将在接下来的介绍中,展示如何使用Angular 2的动画模块。

我们要完成的内容是,在组件A里创建一个新组件B,组件A里有一个按钮,通过点击按钮,来触发组件B中的动画。

所以,第一步,创建新组件,在控制台输入以下命令。

ng g new component newComponent

驼峰命名规则会被系统自动转化为“烤串”命名规则:app-new-component,

在组件A里,我们需要创建一个按钮和新组件的入口标签。

<!--app.component.html-->
<button (click)="change()">走你!</button>
<app-new-component [issildeOut]="sildeOutChange"></app-new-component>

button按钮绑定一个点击事件change(),新组件的入口标签绑定了一个属性“issilderOut”,并给它赋了一个初值“sildeOutChange”,接着我们去写逻辑。

//app.component.ts
sildeOutChange: boolean = true;
issildeOut: boolean;
  
change(): void{
  if(this.issildeOut==true){
    this.sildeOutChange=false;
    this.issildeOut=this.sildeOutChange
  }else{
    this.sildeOutChange=true
    this.issildeOut=this.sildeOutChange
  }    
}

很简单,到目前为止,我们还没涉及动画模块的内容,change()函数的作用就是判断issildeOut这个值为true的时候,点一下就为false,如果为false,点一下就为true了,这里我们并没有直接给issildeOut赋值,而是通过一个中间变量sildeOutChange,具体目的,我稍后介绍,先看组件B的逻辑。

//new-component.componet.ts
import { Component, OnChanges, Input, trigger, state, style, animate, transition  } from '@angular/core';

@Component({
  selector: 'app-new-component',
  templateUrl: './new-component.component.html',
  styleUrls: ['./new-component.component.css'],
  animations: [ // 动画的内容
    trigger('sildeInOut', [
      // state 控制不同的状态下对应的不同的样式
      state('sildeIn' , style({ transform: 'translateX(204px)' })),
      state('sildeOut', style({ transform: 'translateX(0)' })),
      // transition 控制状态到状态以什么样的方式来进行转换
      transition('sildeIn => sildeOut', animate('1000ms')),
      transition('sildeOut => sildeIn', animate('1000ms')),
    ])
  ]
})
export class NewComponentComponent implements OnChanges {
  @Input() issildeOut : boolean;
  sildeInOut = 'sildeIn'; // 避免ngOnChanges()并降低代码复杂度

  ngOnChanges() {
    console.log("ngOnChanges函数已经执行!");
    console.log("在ngOnChanges里,issildeOut值为:"+this.issildeOut);
    this.sildeInOut = this.issildeOut ? 'sildeIn' : 'sildeOut';
  }

}

还记不记得我这篇博文一开始提到的生命周期?ngOnChanges执行于组件生命周期的第一个阶段,组件会判断输入属性是否发生改变,因此,在组件A里,如果我们不通过中间变量直接对issildeOut进行赋值的话,它的作用域仅存在于组件A内部,而无法影响的组件B,事实上,如果不通过中间变量的方式,在组件B里的issildeOut值,将永远是undefined。

再看逻辑,我们引入了执行动画的所有模块,包括:

  • OnChanges:生命周期钩子
  • Input:输入属性
  • trigger:动画触发器
  • state:控制不同状态
  • style:控制样式
  • transition:控制过渡状态(初态→终态/终态→初态)
  • animate:控制过渡状态(动画持续时间/延迟显示/动画执行曲线等)

了解了这些,剩下的我们只需要像操作《英雄指南》那样Ctrl+C/V就可以了。

当然,不要忘了在组件B的视图目标上绑上你写好的动画。

<!--new-component.html-->
<p [@sildeInOut]="sildeInOut">
  new-component works!
</p>

OK,没有问题。

一些我使用过的Angular 2插件

转载于:https://my.oschina.net/u/2414359/blog/876604

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值