A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 AreYouGlad 于 2018-1-8 19:59 编辑

查看更多精彩前端资源


模版引擎
  • Angular集成了强大的模板引擎用于视图的开发, 这套引擎让我们在大部分情况下不用手动操作DOM
  • 接下来我们就基于脚手架工具生成的项目进行学习, 修改的代码主要是项目的src/app目录

插值表达式
  • 打开src/app/app.component.html文件
  • 你会发现模版中含有{{ title }}这样的语法, 这就是插值表达式
  • 它的主要作用是数据的输出与简单的表达式运算

使用尝试
  • 打开src/app/app.component.ts文件, 给AppComponent类添加一个实例属性

[JavaScript] 纯文本查看 复制代码
export class AppComponent {
  title = 'app';
  site = '深圳';     // 自己添加的属性
  constructor() {}
}

  • 然后打开app.component.html, 把{{ title }}插值表达式中的title换成site进行保存
[JavaScript] 纯文本查看 复制代码
<h1>
    Welcome to {{ site }}!
</h1>

  • 然后查看浏览器, 原本的app变成了深圳, 整个过程我们没有涉及到任何DOM操作
  • 回想一下你之前使用过的模版引擎, 是不是觉得Angular的模版引擎很酷

基本运算
  • 插值表达式除了直接输出数据外, 还可以进行简单的运算, 比如下面添加的p标签

[JavaScript] 纯文本查看 复制代码
  <h1>
    Welcome to {{ site }}!
  </h1>
  <p>{{ site == '深圳'? '房子太贵我要离开': '哥甚是怀念深圳蜗居的日子' }}</p>

事件绑定
  • 在Angular中进行事件绑定同样无需手动获取DOM
  • 我们只需要在元素身上添加(事件)=函数的语法即可

尝试点击事件
  • app.component.html文件中添加下面的button元素

[JavaScript] 纯文本查看 复制代码
<!-- 事件绑定语法: (事件名)=函数() -->
<button (click)='clickHandler()'>点我</button>

  • app.component.ts文件中添加对应的clickHandler方法
[JavaScript] 纯文本查看 复制代码
export class AppComponent {
  title = 'app';
  site = '深圳';

  // 点击事件处理函数
  clickHandler(): void {
    console.log('按钮被点击');
  }
}

  • 然后在浏览器中尝试点击按钮, 一个事件绑定就完成了

尝试表单事件
  • 有些时候在事件触发时我们需要拿到对应的事件对象
  • 那么可以在模版中把$event变量传给函数, 下面使用input事件演示
  • 注意: 因为随着代码累加越来越多, 所以下面的代码都是新添加的代码片段

[JavaScript] 纯文本查看 复制代码
<!-- 如果需要事件对象, 那么传入$event即可 -->
<input type="text" (input)='inputHandler($event)'>
// 表单事件处理函数
inputHandler(e): void {
  console.log(`表单最新值为: ${e.target.value}`);
}

数据绑定特性
  • 学习了插值表达式与事件处理之后, 我们可以见识一下Angular的数据绑定特性了
  • 修改刚刚的inputHandler函数为下面的样子, 然后试着在浏览器表单中输入值
  • 你会发现属性发生变化时, angular会自动更新视图, DOM操作你又省了

[JavaScript] 纯文本查看 复制代码
// 表单事件处理函数
inputHandler(e): void {
  this.site = e.target.value;  // 修改site属性的值
}

指令
  • 前面都只是模版最基本的组成部分, 更强大的功能莫过于指令了
  • 在Angular中指令就是具有特殊功能的属性, 这些特殊的属性扩展了html的功能
  • 其实上面的事件绑定语法就是指令的一种, 它使用了(事件名)这样的特殊属性

*ngIf
  • 该指令可控制元素在DOM中的添加与移除

[JavaScript] 纯文本查看 复制代码
<!-- isTure的值控制元素的添加移除 -->
<p *ngIf="isTure">控制我的添加与移除</p>

export class AppComponent {
  title = 'app';
  site = '深圳';
  isTure = false;    // 使用这个值控制元素
}

数据驱动开发思想
  • 尝试在页面中添加一个按钮, 控制元素的添加隐藏
  • 你会发现这个业务逻辑我们只需修改属性即可, 维护数据是我们的根本, 这就是数据驱动

[JavaScript] 纯文本查看 复制代码
<!-- *ngIf, isTure的值控制元素的添加移除 -->
<div>
  <p *ngIf="isTure">控制我的添加与移除</p>
  <button (click)='clickAddOrRemove()'>{{ isTure? '移除': '添加' }}</button>
</div>

export class AppComponent {
  title = 'app';
  site = '深圳';
  isTure = false;    // 使用这个值控制元素

  // 点击事件, 只要修改isTure属性, 就可以控制元素的添加移除
  clickAddOrRemove(): void {
    this.isTure = !this.isTure;
  }
}

*ngFor
  • 可遍历数组, 依据数据结构渲染一个列表

基本使用
[JavaScript] 纯文本查看 复制代码
<!-- *ngFor, 里面采用的语法是固定格式 -->
<ul>
  <li *ngFor="let city of cityList">{{ city }}</li>
</ul>

export class AppComponent {
  title = 'app';
  site = '深圳';
  isTure = false;    // 使用这个值控制元素
  cityList = [
    '北京',
    '上海',
    '广州',
    '深圳'
  ];
}
拿到数组下标
  • ngFor除了可以拿到值, 还可以拿到下标

[JavaScript] 纯文本查看 复制代码
<!-- *ngFor, 下面是获取下标并使用的语法 -->
<ul>
  <li *ngFor="let city of cityList; let i = index">{{ i }} : {{ city }}</li>
</ul>
性能优化



  • ngFor指令中可以通过设置trackBy属性来优化你的视图渲染, 属性值要求是个函数: https://angular.cn/api/core/TrackByFunction
  • Angular内部会使用这个值作为元素的ID, 当数据变化时, 新旧ID会进行比较以判断是否有必要重新渲染这个元素

  • 大多数情况下我们无需设置它, 如果我们渲染的数据比较复杂可能需要考虑一下

  • PS: 这里通过修改部分数据, 来给大家演示当数据变化时, angular会有选择性的重新渲染部分元素


[JavaScript] 纯文本查看 复制代码
<ul>
  <!-- *ngFor, 下面是添加trackBy的语法, trackBy要求赋值一个函数, 这里把trackByCity赋了过去 -->
  <li *ngFor="let city of cityList; let i = index; trackBy: trackByCity">{{ i }} : {{ city }}</li>
</ul>

export class AppComponent {
  cityList = [
    '北京',
    '上海',
    '广州',
    '深圳'
  ];
  // trackBy函数会自动接收到ngFor遍历到的下标与item
  // 这里因为数据结构比较简单, 把下标与值拼在一起作为元素ID返回
  trackByCity(index: number, item: any) {
          return index + '_' + item;
  }
}
trackBy简写


  • 如果你的数据本身就具有ID这样的唯一属性, 那么你可以省略函数的编写

  • 因为trackBy的值也可以是一个基本数据类型, 查看下面的代码


[JavaScript] 纯文本查看 复制代码
<ul>
  <!-- 这里需要注意的是里面赋值时使用的?号, 没有它将报错 -->
  <li *ngFor="let user of userList; trackBy: user?.id">{{ user.name }}</li>
</ul>

export class AppComponent {
  userList = [
    {name: '花花', age: 16, id: 10001},
    {name: '草草', age: 18, id: 10002}
    {name: '云云', age: 20, id: 10003},
    {name: '朵朵', age: 15, id: 10004}
  ];
}
ngSwitch指令组



  • 有些时候我们需要根据一个变量的值来展示不同的内容
  • 使用*ngIf可以解决我们的问题, 但是他们看起来并不是一组, 使用ngSwitch指令组会更好
  • ngSwitch指令组由三个不同指令构成:[ngSwitch] *ngSwitchCase *ngSwitchDefault

  • 其中[]包起来的指令叫属性指令, 这种指令会修改DOM对象的属性

  • 然后*号开头的指令叫结构指令, 这种指令会进行DOM的添加移除


[HTML] 纯文本查看 复制代码
<!-- ngSwitch指令组,这里使用以前的site数据进行控制 -->
<!-- 其中的*ngSwitchCase因为不使用数据绑定,而是写死的字符串,所以里面的值添加单引号包裹 -->
<div [ngSwitch]='site'>
  <p *ngSwitchCase="'北京'">北京冬天有暖气</p>
  <p *ngSwitchCase="'上海'">上海冬天有空调</p>
  <p *ngSwitchCase="'深圳'">深圳冬天要裹被</p>
  <p *ngSwitchDefault>不管在哪, 只要不过冬天就好</p>
</div>
属性指令 - 原生的DOM属性修改


  • 属性指令的语法是使用[]包起来, 里面可以书写angular扩展的DOM属性, 也可以写原生DOM属性

  • 下面给出的范例都是操作原生的DOM属性


innerHTML属性
[JavaScript] 纯文本查看 复制代码
<!-- 使用[]属性指令语法动态修改元素的innerHTML -->
<div [innerHTML]="tpl"></div>

export class AppComponent {
        title = 'app';
        tpl = `<div>
            <h4>我是数据里的字符串模版</h4>
            <h4>我是数据里的字符串模版</h4>
    </div>`;
}
其他属性范例
[JavaScript] 纯文本查看 复制代码
<div>
  <a [href]="aHref">点击跳转</a>
  <img [src]="imgSrc"/>
</div>

export class AppComponent {
  aHref = 'http://www.baidu.com';
  imgSrc = 'http://www.baidu.com/img/bd_logo1.png';
}
container容器



  • Angular不允许在一个元素上使用多个结构性指令(*打头的都为结构性指令)

  • 那么可以通过嵌套一个<ng-container>标签, 给它添加控制指令来解决

  • 这个元素在渲染时不会在页面上留下任何痕迹, 作用只是单纯的增加一些逻辑处理


错误范例
  • 下面使用ngFor生成多个li标签, 但是又进一步通过ngIf控制li标签的渲染, 最终报错

[HTML] 纯文本查看 复制代码
<ul>
  <li *ngFor="let city of cityList; let i = index" *ngIf="i % 2 == 0">{{ i }} : {{ city }}</li>
</ul>
解决方案
[HTML] 纯文本查看 复制代码
<!-- 不能在一个元素上使用多个结构性指令,那么可以嵌套ng-container标签解决 -->
<ul>
  <ng-container *ngFor="let city of cityList; let i = index">
    <li *ngIf="i % 2 == 0">{{ i }} : {{ city }}</li>
  </ng-container>
</ul>
[(ngModel)] - 双向数据绑定



  • 这是一个用于表单的双向数据绑定指令, 前面我们使用的插件表达式或指令都是单向的数据绑定

  • 单向的特点是数据发生变化, 视图跟着变化

  • 但是对于表单元素来说, 我们希望的是表单变了数据变, 数据变了表单变


准备工作


  • 使用这个指令我们需要从'@angular/forms'中导入FormsModule模块然后配置到根模块依赖中

  • 首先打开根模块app/app.modules.ts文件, 然后编写下面的代码


[JavaScript] 纯文本查看 复制代码
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

// 导入表单模块
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule     // 把表单模块配置进来
  ],
  providers: [
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
使用
[JavaScript] 纯文本查看 复制代码
<div>
  <h2>请输入新密码</h2>
  <!-- 使用了双向数据绑定后, password的值会自动显示到表单, 表单改变时password也自动改变 -->
  <input type="text" [(ngModel)]="password">
  <span>{{ password }}</span>
</div>

export class AppComponent {
        password = '默认密码';
}

1 个回复

倒序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马