Angular-cli 环境搭建,组件,组件的数据渲染,父子组件传值

Angular cli-1

Angular 脚手架的脚本是 TypeScript

环境搭建

使用 node.js 配置 Angular-cli 的环境。
命令:

npm install -g @angular/cli

创建新的项目

ng new my-app

ng new 命令执行时,会提示要把哪些特性添加到应用中,按 EnterReturn 键可以接收默认值。

运行项目

cd my-app
ng serve --open

目录结构简介

# 一级目录介绍
    node_modules:
        第三方依赖包存放目录
    e2e
        端到端的测试目录  用来做自动测试的
    src
        应用源代码目录  
    angular.json
        Angular命令行工具的配置文件。后期可能会去修改它,引一些其他的第三方的包
    karma.conf.js
        karma是单元测试的执行器,karma.conf.js是karma的配置文件
    package.json
        是一个标准的npm工具的配置文件,这个文件里面列出了该应用程序所使用的第三方依赖包。实际上我们在新建项目的时候,等了半天就是在下载第三方依赖包。下载完成后会放在node_modules这个目录中,后期我们可能会修改这个文件。
    README.md
        说明文件
    tslint.json
        是tslint的配置文件,用来定义TypeScript代码质量检查的规则,不用管它

# src目录介绍
    app目录
        包含应用的组件和模块
    assets目录
        资源目录,存储静态资源的  比如图片
    environments目录
        环境配置。Angular是支持多环境开发的,我们可以在不同的环境下(开发环境,测试环境,生产环境)共用一套代码,主要用来配置环境的
    index.html
        整个应用的根html,程序启动就是访问这个页面
    main.ts
        整个项目的入口点,Angular通过这个文件来启动项目
    polyfills.ts
        主要是用来导入一些必要库,为了让Angular能正常运行在老版本下
    styles.css
        主要是放一些全局的样式

组件

一、创建组件和目录结构

在项目的命令行输入创建一个组件 LeftMenu 的命令:

ng generate component LeftMenu

app 目录下会自动生成组件的相关文件:

left-menu.component.css
    当前组件的css
left-menu.component.html
    当前组件的html
left-menu.component.spec.ts
    当前组件的测试文件
left-menu.component.ts
    当前组件的脚本

二、组件的脚本

一个组件被创建好之后,它的脚本代码中会有一些默认生成的内容:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-left-menu',
  // 当前组建类结构的路径
  templateUrl: './left-menu.component.html',
  // 当前组建类样式的路径
  styleUrls: ['./left-menu.component.css']
})
export class LeftMenuComponent implements   OnInit {
  // 导出当前组建类,在类中定义组件的应用逻辑,为视图提供支持。 组件通过一些由属性和方法组成的 API 与视图交互

  // 组建类的构造函数
  constructor() { }

  // 组建类初始化的生命周期钩子函数
  ngOnInit() {
  }

}

@Component 详解
@Component 是一个装饰器,绘指出紧随其后的这个类是个组建类(当前示例中为 LeftMenuComponent),并规定其元数据。

如果一个类没有被 @Component 装饰器修饰,那么这个类就是个普通的类,不代表任意组件,你只能使用这个类完成基础的 JS 逻辑交互。

  • selector: 是一个 CSS 选择器,他会告诉 Angular,一旦在模板 HTML 中找到了这个选择器对应的标签,就创建并插入该组件的一个实例。 比如,如果应用的 HTML 中包含 <app-left-menu></app-left-menu>Angular 就会在这些标签中插入一个 ``LeftMenuComponent` 实例的视图。
  • templateUrl: 该组件的 HTML 模板文件相对于这个组件文件的地址。 另外,你还可以用 template 属性的值来提供内联的 HTML 模板。 这个模板定义了该组件的宿主视图。
  • styleUrls: 作用于当前组件的所有的样式列表。

一个组件被创建之后可以在任意组件中直接使用组件的 @Component 中的 selector 调用组件

组件的数据渲染和事件绑定

一、组件的数据声明

// left-menu.component.ts
import { Component } from '@angular/core'

@Component({
  selector: 'app-left-menu',
  templateUrl: './left-menu.component.html'
})
export class LeftMenuComponent {
  // 方式一
  title = '菜单栏';
  list = ['孙权', '周瑜', '鲁肃', '吕蒙', '陆逊'];
  className = 'active';

  // 方式二 
  flag: boolean;
  constructor() {
    this.flag = true;
  }
  ngOnInit() {}
  onBtnClick() {
    this.flag = false;
  }
}

通过不同方式声明的组件的数据,意义和使用方式都是相同的。

二、数据绑定

Angular 支持双向数据绑定,这是一种对模板中的各个部件与组件中的各个部件进行协调的机制。 往模板 HTML 中添加绑定标记可以告诉 Angular 该如何连接它们。

1. 插值表达式

<!-- left-menu.component.html -->
<h1>{{ title }}</h1>
<h2>{{ flag ? '海子' : '三体' }}</h2>
<h3>{{ flag && '仙逆' }}</h3>

2. 属性中动态的绑定数据

<!-- left-menu.component.html -->
<h1 [class]="className">{{ title }}</h1>
<input [value]="list[0]" />

3. 将组建类的函数绑定给组件中的某个事件

<!-- left-menu.component.html -->
<button (click)="onBtnClick()">点我</button>

4. 双向数据绑定

双向数据绑定主要应用于模板驱动表单中。Angular 提供了 ngModel 指令实现数据双向绑定。

但是要使用 ngModel 需要在导入 FormsModule 包:

// app.module.ts
...
import {FormsModule} from '@angular/forms';

@NgModule({
  ...
  imports: [
    ...
    FormsModule
  ]
  ...
})
export class AppModule { }

<!-- left-menu.component.html -->
<input [(ngModel)]="title" />

三、管道修饰符

我们可以把管道理解为数据过滤器。

Angular管道可以让你在模板中声明显示值的转换逻辑。 带有 @Pipe 装饰器的类中会定义一个转换函数,用来把输入值转换成供视图显示用的输出值。

Angular 自带了很多管道,比如 date 管道和 currency 管道。

你可以把管道串联起来,把一个管道函数的输出送给另一个管道函数进行转换。 管道还能接收一些参数,来控制它该如何进行转换。比如,你可以把要使用的日期格式传给 date 管道:

<!-- Default format: output 'Jun 15, 2015'-->
<p>Today is {{1566635864356 | date}}</p>

<!-- fullDate format: output 'Monday, June 15, 2015'-->
<p>The date is {{1566635864356 | date:'fullDate'}}</p>

<!-- shortTime format: output '9:43 AM'-->
<p>The time is {{1566635864356 | date:'shortTime'}}</p>

四、数据渲染的指令

Angular 的模板是动态的。当 Angular 渲染它们的时候,会根据指令给出的指示对 DOM 进行转换。 指令就是一个带有 @Directive() 装饰器的类。

组件从技术角度上说就是一个指令,但是由于组件对 Angular 应用来说非常独特、非常重要,因此 Angular 专门定义了 @Component() 装饰器,它使用一些面向模板的特性扩展了 @Directive() 装饰器。

除组件外,还有两种指令:结构型指令(ngFor,ngIf)属性型指令( [(ngModel)] 就是一个属性型指令)Angular 本身定义了一系列这两种类型的指令,你也可以使用 @Directive() 装饰器来定义自己的指令。

像组件一样,指令的元数据把它所装饰的指令类和一个 selector 关联起来,selector 用来把该指令插入到 HTML 中。 在模板中,指令通常作为属性出现在元素标签上,可能仅仅作为名字出现,也可能作为赋值目标或绑定目标出现。

结构型指令通过添加、移除或替换 DOM 元素来修改布局。 这个范例模板使用了两个内置的结构型指令来为要渲染的视图添加程序逻辑

简单示例:

1. ngFor

<!-- left-menu.component.html -->
<ul>
  <!-- 
    list 为组件类中声明的数据
    item 相当于此次循环的一个局部变量,代表每次循环到的数据
   -->
  <li *ngFor="let item of list">{{ item }}</li>
</ul>

2. ngIf

<!-- left-menu.component.html -->
<h1 *ngIf="flag">{{ title }}</h1>

组件间的数据交互

Angular 提供了 @Input@Output@ViewChild 来实现组件之间的数据通信

示例需求,实现父级组件 Father 和 子级组件 Kid 之间的数据交互。

一、父传子(@Input)

// father.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-father',
  templateUrl: './father.component.html',
  styleUrls: ['./father.component.css']
})
export class FatherComponent implements OnInit {
  tip = '我是来自父组件的数据';
  constructor() { }

  // 父组件中的函数
  fnOfFather() {
    /* 
      *****
      当前组件调用该函数,this 为当前组建类
      如果将当前函数传递给子组件,在子组件中调,this 指向自组建类
     */
    console.log('fnOfFather');
    console.log(this.title);
  }

  ngOnInit() {
  }
}
<!-- father.component.html -->
<!-- 
  在父组件中调用 Kid 子组件
  msg 和 fn是 传递给子组件的数据指针,子组件通过这个指针接受数据
  如果 msg 不需要读取变量 tip 的值,那 msg 不需要加 [] 修饰
   -->
<app-kid [msg]="tip" [fn]="fnOfFather"></app-kid>

子组件中要接收

// kid.component.ts
// 导入 @Input 装饰器
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-kid-content',
  templateUrl: './kid-content.component.html',
  styleUrls: ['./kid-content.component.css']
})
export class KidComponent implements OnInit {
  // 通过 @Input 装饰器接收数据,接收之后可以直接加以使用
  @Input()msg: string;
  @Input()fn: any;
  constructor() { }

  ngOnInit() {
    this.fn(); // 调用 fn 会执行 Father 中的 fnOfFather 函数
  }
}
<!-- kid.component.html -->
<h1>{{ msg }}</h1>

二、子传父(@Output 和 EventEmitter)

点击 <Kid> 组件中的某个按钮,向父级组件传递一个数据。

<!-- kid.component.html -->
<!-- 
  点击按钮时,调用当前组件的 toFather 函数
 -->
<button (click)="toFather()">传值</button>
// kid.component.ts 导入传参需要使用的 @Output 装饰器和 EventEmitter 类
import { Component, OnInit, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'kid-menu',
  templateUrl: './kid.component.html',
  styleUrls: ['./kid.component.css']
})
export class KidComponent implements OnInit {
  // 创建一个 EventEmitter 对象
  // 并规定使用这个对象的 emit 函数导出事件时,参数为一个对象
  // 将这个对象定义成当前类的私有属性,并使用 @Output 装饰器修饰
  @Output() private outer = new EventEmitter<object>();
  list = ['孙权', '周瑜', '鲁肃', '吕蒙', '陆逊'];
  ngOnInit() {
    this.fn();
  }
  toFather() {
    this.outer.emit(this.list);
  }
}

父组件调用子组件时,需要预留接口接受子组件通过事件传递的参数:

<!-- father.component.html -->
<!-- 
  使用当前组件中的 fn 函数和 $event 对象,接受子组件触发事件时导出的事件及参数
 -->
<app-kid (outer)="fn($event)"></app-kid>
// father.component.ts
// ...
export class CenterContentComponent implements OnInit {
  fn(param) {
    // 当子组件中的传值按钮被点击时,父组件中的 fn 函数会被自动调用
    // param 是子组件触发事件的同事传递过来的参数
    console.log(param);
  }
  ngOnInit() {
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章