angular 4+中关于父子组件传值的示例

 1 home.component.ts
 2 
 3 import { Component, OnInit } from '@angular/core';
 4 
 5 @Component({
 6   selector: 'app-home',
 7   templateUrl: './home.component.html',
 8   styleUrls: ['./home.component.css']
 9 })
10 export class HomeComponent implements OnInit {
11 
12   constructor() { }
13 
14   ngOnInit() {
15   }
16 
17   app_substring: string = "<app-subcomponet [msg]='msg' [parentFun]='parentFun'></app-subcomponet>";
18   app_substringtwo:string="在parent.component的模板中使用 <app-subcomponet (childbroadcastevent)=parentsubcribe($event)";
19   
20 }
header.component.html

<!-- <p>header works!</p> -->
<h1 class="header">this is {{msg}}</h1>
<hr />
<button (click)='childFun()'>调用父组件的方法</button>
<button (click)='childOutFun()'>子组件广播事件向父组件传值</button>
<hr />
<!-- ----------------header data--------------------
{{title}}---{{msg}} -->
header.component.ts

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

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit, OnDestroy, OnChanges {
  title = 'this is header\'s title';

  //模板参数定义方式,注意,input传入的是对象,即可以是属性,还可以是方法

  ///接收父组件的属性
  @Input() msg: string;

  @Input() parentFun: any;

  @Output() childOut = new EventEmitter<string>();

  message: string;

  constructor() {
    console.log('constructor...' + this.msg);
  }

  ngOnInit() {
    // this.msg = 'this is header data'
    console.log('ngOnInit...' + this.msg);
  }

  ngOnDestroy() {
    console.log('ngOnDestroy...' + this.msg);
  }

  ngOnChanges() {
    console.log('ngOnChanges...' + this.msg);
  }

  childFun() {
    this.message = '这是header传给父组件的参数';
    this.parentFun(this.message);
  }

  ///子组件定义一个output的属性,来作为父组件的引用,进行广播
  ///父组件通过,监听这样一个子组件的广播属性,来响应子组件的操作 注意:由于是事件,所以用 ()
  childOutFun() {
    this.childOut.emit('子组件向父组件广播的emitdata');
  }


  childFunForParent() {
    alert('供父组件调用的方法');
  }
}
news.component.ts

import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit, AfterViewInit {
  @ViewChild('headerchild', { read: '', static: true }) headerchild;
  public news: any[];
  protected spanhtml: string = '<h2>测试显示HTML代码,是否能解析成功</h2>';
  protected id: Number = 100;

  public search: string = '';
  public msg: string = '这是news的Header';



  constructor(private http: HttpClient) {
    this.news = [
      {
        'cateName': '宝马',
        'brand': [{ 'title': '宝马X1' },
        { 'title': '宝马X1' },
        { 'title': '宝马X2' },
        { 'title': '宝马X3' },
        { 'title': '宝马X4' }]
      },
      {
        'cateName': '奥迪',
        'brand': [{ 'title': '奥迪q1' },
        { 'title': '奥迪q2' },
        { 'title': '奥迪q3' },
        { 'title': '奥迪q4' },
        { 'title': '奥迪q5' }]
      },
      {
        'cateName': '中华',
        'brand': []
      }
    ];
  }
  ngOnInit() {
  }

  ngAfterViewInit() {

  }

  getApiData() {
    let url: string = 'https://itunes.apple.com/search';
    let searchUrl = `${url}?term=${this.search}&media=music&limit=20`;
    this.http.jsonp(url, 'callback').subscribe(
      function (data) { console.log(data) },
      function (error) { console.log(error) })
  }

  ///父组件通过属性传值公开给子组件的方法
  parentFun(msg) {
    alert(msg);
  }

  ///父组件监听的子组件方法
  parentAimedFun(e) {
    alert(e);
  }

  ////父组件通过viewchild直接调用子组件的方法
  excuteChildFunByViewChild() {
    this.headerchild.childFunForParent();
  }

}
news.component.html

<app-header [msg]='msg' [parentFun]='parentFun' (childOut)='parentAimedFun($event)' #headerchild></app-header>

<button (click)="headerchild.childFunForParent()">试试父组件执行子组件方法</button>
<button (click)="excuteChildFunByViewChild()">试试父组件通过viewchild执行子组件方法</button>

<br>
<p>news works!</p>
<span [innerHTML]="spanhtml"></span>
<div [id]="id"></div>

<div>
  <ul>
    <li *ngFor="let item of news;let key=index">
      系列:{{item.cateName}}<br>
      车型数量:{{item.brand.length}}
      <ol>
        <div *ngIf="item.brand.length>0">
          <li *ngFor="let car of item.brand;let key=index">
            车型:{{car.title}}
          </li>
        </div>
        <div *ngIf="item.brand.length==0">
          暂无更多数据
        </div>
      </ol>
    </li>
  </ul>
</div>

<hr />
<h2>Jsonp查询数据</h2>
输入关键字:<input type="text" [(ngModel)]="search" />
<button (click)="getApiData()">点击查询</button>

父组件向子组件传值的方法:

<br>

1.通过对子组件的引用,给子组件绑定 属性,如

<div>{{app_substring}}</div>

<br>

其中:msg parentFun 都是 父组件给子组件绑定的属性

<br>

子组件通过@input() 属性名:type(类型 不知道则为any)来获取

父组件的属性传值

<br />

例如:<br />

@Input() msg: string;<br />

@Input() parentFun: any;

2.关于output的用法

output是和eventemitter一起使用来实现父子组件传值的

原理:

a 子组件进行事件广播

b 父组件在引用的子组件时,监听广播事件,既然是事件,那么写法肯定是(事件名称)='父组件的事件函数()'

<div>{{app_substringtwo}}</div>

app-subcomponet的childbroadcastevent为:

@output() childbroadcastevent=new EventEmitter<T>() 注意:T即为传播的数据类型

childOutEvent(){

this.childbroadcastevent.emit('some data to parent');

}

即发布订阅模式,来实现值的传输

当子组件的某个操作触发childOutEvent的时候,函数调用:childbroadcastevent 广播事件,而父组件监听这个事件

所以就可以接受来自子组件的数据

3.使用viewchild

父组件申明 @viewchild('子组件的selector') 这时候,相当于拿到子组件的实例,然后就可以直接调用子组件的方法或者使用子组件的属性了

可以理解为代理模式