全栈Web开发者"老和"讲全栈WEB全栈技术

Angular 5.X 学习笔记——component之间的数据

2018-04-14  本文已影响33人  全栈开发之道
序言

这次学习笔记,来自国外的一篇教学案例,好东西就得分享。

Angular Input Output Tutorial Example From Scratch

Step 1: Install Angular Project via AngularCLI
Step 2: Create parent and child components.
Step 3: Define HTML for parent component
Step 4: Define HTML for child component
Step 5: Use Input to display parent component value
Step 6: Pass value from child to parent component

代码实现与解析

第一步 创建一个project

ng new input

说明:
(1) 在 AngularJS时代,创建一个NG工程很简单,只是在html文件中,引入 AngularJS即可。 进入 Angular 新时代后,是通过CLI 来创建工程的。 所以需要事先安装Angular 的 CLI。 而且,一旦创建就要默认生成很好很多文件, 自然,这个创建过程需要耐心的等待,花些时间是必须的。
(2)在这个创建工程中,不仅仅是create 了一些文件,而且还自动生成了它的依赖包,也就是说,自动执行力 npm install。 整个工程 380M,一行代码还没写呢!

(3) 一旦创建成功,你肯定会迫不及待地想运行看看效果。 通常,会不加思索地运行它。

ng serve -o

奇怪现象产生了,咦,不是说好了 hello world 会自动生成的吗? 怎么报这个错呢? 吓死宝宝了。 呵呵

image.png

当然,聪明的你,会想起百度学习法。在百度上搜索下看看, 搜索:
You seem to not be depending on "@angular/core". This is an error.

神人多了去了,招数也多了去了,有人告诉你,重新安装 Angular CLI; 有人告诉你重新 npm install, 甚至也有告诉你,重新安装 node.js 就差让你换一台电脑了。


其实哪里有这么复杂,报错的意思,并不是说依赖关系出了问题,而是根本没找见 @angular/core 。 经验告诉我们,找不见文件,通常是路径出了问题。

我们刚才创建了的工程路径是 input, 而指令所在的路径根本不是 input 啊! 这时候的你,肯定恍然大悟,原来如此!

进入到该工程所在路径:

cd input

这时,再来运行以下

ng serve -o

奇迹出现了,世界是多么的其妙! 啥也不说了,看图吧:

image.png

重要的事情说三遍: 创建工程后,一定要进入到该工程所在的路径!
重要的事情说三遍: 创建工程后,一定要进入到该工程所在的路径!
重要的事情说三遍: 创建工程后,一定要进入到该工程所在的路径!


Step 2: Create parent and child components.

ng g c parent
ng g c parent

说明:
(1)此时,Angular APP 还在运行中,我们要执行新的命令了,如何退出呢?—— Ctrl+C
创建组件: g: generate ; c :component
(2)虽然创建了两个component,因为还没有关联起来,即便运行,其结果也不会有什么变化。

APP 的入口是 app.component.html ,在入口文件中,添加以下代码:

<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
  <app-parent></app-parent>
</div>

说明:
<app-parent></app-parent> 这个位置,是预留给 parent.component.html 的。

Step 3: Define HTML for parent component.

在 parent.component.html 中,添加以下代码:

<h3>Parent Component</h3>
<label>Bitcoin price</label>
<input type="text" />
<p>Value of child component is: </p>

此时,再来运行,看到的首页变化了。 parent.component.html 文件加载了进来,显示如下:

image.png

思路: 在parent页面上输入文字, 在child 页面上显示文字。 并且, parent 与 child 在同一个页面上。所以,需要在 parent.component.html 中,引入 <app-child>

首先,在child.component.html 文件中,添加以下代码:

<h3>Child Component</h3>
<label>Child Component</label>
<input type="text" />
<p>Value of parent component is: </p>

接着, 在parent.component.html 文件中,引入<app-child>
。代码如下:

<h3>Parent Component</h3>
<label>Bitcoin price</label>
<input type="text" />
<p>Value of child component is: </p>
<app-child> </app-child>

再来运行下,结果如下:


image.png

组件之间的传值,就要开始了!

Step 5: Use Input to display parent component value

@Input 粉墨登场!

详情参考: @Input的应用

Decorator : 修饰符
A decorator is a function that is invoked with @ prefix and followed by class, method, property.
例如: @Input()

踩“坑”开始,请注意!!

在 parent.component.html 文件中,修改代码如下:

<input type="text" #pcomponent  (keyup)="0"/>
<app-child [PData]="pcomponent.value"></app-child>

说明:

想获取 <input> 里面的值,怎么办?
简单方法: 设置 <input> 的 reference (参考), 注意写法:
#pcomponent

再将该值,传给 child 页面。方法是:

<app-child [PData]="pcomponent.value"></app-child>

把 <input> 的值,传给一个变量 PData 。 注意, 加上 [ ], 起到“插补”的作用。

在 child.component.html 文件中,添加代码:

export class ChildComponent implements OnInit {

  @Input() PData: string;
  constructor() { }

  ngOnInit() {
  }

}

说明,特别注意:

@Input() PData: string;

@Input() 是一体的,不能分开。
PData 是一个变量,这个变量来自 parent.component.html 的设定

这时候,再来运行,看到如下结果:

image.png

如果没有出现你期望的结果,可能出现的“坑”,如下:

“坑”(一):
parent.component.html 中,特别注意这一行代码:

<app-child [PData]="pcomponent.value"></app-child>

[PData]="pcomponent.value" 必须写在 <app-child> 里面,切不可写在标签的之间:
<app-child> [PData]="pcomponent.value" </app-child>

“坑”(二):

[PData]="pcomponent.value" 的赋值必须是一个变量。 简单的直接赋值是不可以的。 不可以这样写:
[PData]="test data"

说明:
Angular 5.X 传值的玄妙之处就在于此。 [ ] 插补(interpolation)的用法。 如果还没理解,先跳过去,记住它的用法就可以了。

Step 6: Pass value from child to parent component.

思路:在child 中创建一个 Event, 通过 @Output 修饰符,供 Parent 调用;

parent 无法获取到child,所以 parent 监听 child 的事件,当事件触发时,把child 的值传给 parent。

在 child.component.html 中,添加代码:

<h3>Child Component</h3>
<label>Child Component</label>
<input type="text" #ccomponent (keyup)="onChange(ccomponent.value)"/>

<p>Value of parent component is: {{ PData }}</p>

在 child.component.ts 中,添加代码:

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {

  @Input() PData: number;
  @Output() childEvent = new EventEmitter();
  constructor() { }
  onChange(value) {
    this.childEvent.emit(value);
  }

  ngOnInit() {
  }

}

代码解读:
(1)在 ts 文件中声明一个 onChange 方法,并在 html 的 <input> 标签中调用 onChange 方法。

(2) 为了让 parent 监听 child的事件,通过 @Output() 来声明。
@Output() childEvent = new EventEmitter();
这时候, parent 就可以监听 childEvent 事件了。要注意,这个事件是可以传参的。 具体传什么参数呢?

this.childEvent.emit(value);

传的是这个value。就看给这个参数输入什么了。

接下来, 在 parent.component.html 文件中,绑定这个事件和参数,如下:

<app-child [PData]="pcomponent.value" (childEvent)="CData=$event"></app-child>

同时,在 parent.component.ts 中,声明一个变量:

// parent.component.ts
public CData: number;

在 parent.component.html 中,显示 child的输入值:

// parent.component.html
<h3>Parent Component</h3>

<label>Parent Component</label>
<input type="text" #pcomponent (keyup)="0"/>

<p>Value of child component is: {{ CData }}</p>
<app-child [PData]="pcomponent.value" (childEvent)="CData=$event"></app-child>

代码解读:

为什么要声明 CData 这个变量呢? 套路是: 先赋值给一个变量,然后,在其他地方,调用这个变量。 很通俗吧!

运行结果:

image.png
上一篇 下一篇

猜你喜欢

热点阅读