den*_*ard 110 javascript typescript angular
我有一个ListComponent.在ListComponent中单击某个项目时,该项目的详细信息应显示在DetailComponent中.两者都在屏幕上同时出现,因此不涉及路由.
如何告诉DetailComponent单击ListComponent中的哪个项目?
我考虑过将一个事件发送到父(AppComponent),并让父设置在DetailComponent上使用@Input设置selectedItem.id.或者我可以使用具有可观察订阅的共享服务.
编辑:通过事件+ @Input设置所选项目不会触发DetailComponent,但是,如果我需要执行其他代码.所以我不确定这是一个可以接受的解决方案.
但是这两种方法看起来都比Angular 1的做法复杂得多,这种做法要么通过$ rootScope.$ broadcast或$ scope.$ parent.$ broadcast.
由于Angular 2中的所有内容都是组件,我很惊讶没有关于组件通信的更多信息.
有没有其他/更直接的方法来实现这一目标?
Ale*_*x J 63
更新到rc.4: 当尝试在角度2中的兄弟组件之间传递数据时,现在最简单的方法(angular.rc.4)是利用angular2的层次依赖注入并创建共享服务.
这将是服务:
import {Injectable} from '@angular/core';
@Injectable()
export class SharedService {
dataArray: string[] = [];
insertData(data: string){
this.dataArray.unshift(data);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,这里将是PARENT组件
import {Component} from '@angular/core';
import {SharedService} from './shared.service';
import {ChildComponent} from './child.component';
import {ChildSiblingComponent} from './child-sibling.component';
@Component({
selector: 'parent-component',
template: `
<h1>Parent</h1>
<div>
<child-component></child-component>
<child-sibling-component></child-sibling-component>
</div>
`,
providers: [SharedService],
directives: [ChildComponent, ChildSiblingComponent]
})
export class parentComponent{
}
Run Code Online (Sandbox Code Playgroud)
和它的两个孩子
孩子1
import {Component, OnInit} from '@angular/core';
import {SharedService} from './shared.service'
@Component({
selector: 'child-component',
template: `
<h1>I am a child</h1>
<div>
<ul *ngFor="#data in data">
<li>{{data}}</li>
</ul>
</div>
`
})
export class ChildComponent implements OnInit{
data: string[] = [];
constructor(
private _sharedService: SharedService) { }
ngOnInit():any {
this.data = this._sharedService.dataArray;
}
}
Run Code Online (Sandbox Code Playgroud)
孩子2(这是兄弟姐妹)
import {Component} from 'angular2/core';
import {SharedService} from './shared.service'
@Component({
selector: 'child-sibling-component',
template: `
<h1>I am a child</h1>
<input type="text" [(ngModel)]="data"/>
<button (click)="addData()"></button>
`
})
export class ChildSiblingComponent{
data: string = 'Testing data';
constructor(
private _sharedService: SharedService){}
addData(){
this._sharedService.insertData(this.data);
this.data = '';
}
}
Run Code Online (Sandbox Code Playgroud)
现在:使用此方法时需要注意的事项.
Dud*_*udi 26
如果有2个不同的组件(不是嵌套组件,父\ child\grandchild),我建议你:
MissionService:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MissionService {
// Observable string sources
private missionAnnouncedSource = new Subject<string>();
private missionConfirmedSource = new Subject<string>();
// Observable string streams
missionAnnounced$ = this.missionAnnouncedSource.asObservable();
missionConfirmed$ = this.missionConfirmedSource.asObservable();
// Service message commands
announceMission(mission: string) {
this.missionAnnouncedSource.next(mission);
}
confirmMission(astronaut: string) {
this.missionConfirmedSource.next(astronaut);
}
}
Run Code Online (Sandbox Code Playgroud)
AstronautComponent:
import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'my-astronaut',
template: `
<p>
{{astronaut}}: <strong>{{mission}}</strong>
<button
(click)="confirm()"
[disabled]="!announced || confirmed">
Confirm
</button>
</p>
`
})
export class AstronautComponent implements OnDestroy {
@Input() astronaut: string;
mission = '<no mission announced>';
confirmed = false;
announced = false;
subscription: Subscription;
constructor(private missionService: MissionService) {
this.subscription = missionService.missionAnnounced$.subscribe(
mission => {
this.mission = mission;
this.announced = true;
this.confirmed = false;
});
}
confirm() {
this.confirmed = true;
this.missionService.confirmMission(this.astronaut);
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this.subscription.unsubscribe();
}
}
Run Code Online (Sandbox Code Playgroud)
资料来源:家长和孩子通过服务进行沟通
Can*_*ner 11
一种方法是使用共享服务.
但是我发现以下解决方案更简单,它允许在两个兄弟之间共享数据.(我仅在Angular 5上测试过这个)
在您的父组件模板中:
<!-- Assigns "AppSibling1Component" instance to variable "data" -->
<app-sibling1 #data></app-sibling1>
<!-- Passes the variable "data" to AppSibling2Component instance -->
<app-sibling2 [data]="data"></app-sibling2>
Run Code Online (Sandbox Code Playgroud)
APP-sibling2.component.ts
import { AppSibling1Component } from '../app-sibling1/app-sibling1.component';
...
export class AppSibling2Component {
...
@Input() data: AppSibling1Component;
...
}
Run Code Online (Sandbox Code Playgroud)
小智 9
这里有一个讨论.
https://github.com/angular/angular.io/issues/2663
Alex J的答案很好,但截至2017年7月,它已不再适用于当前的Angular 4.
这个plunker链接将演示如何使用共享服务和可观察的兄弟姐妹之间进行通信.
https://embed.plnkr.co/P8xCEwSKgcOg07pwDrlO/
指令在某些情况下可以“连接”组件。实际上,连接的东西甚至不需要是完整的组件,有时候,如果不是的话,它会更轻巧,实际上更简单。
例如,我有一个Youtube Player组件(包装Youtube API),我想要一些控制器按钮。这些按钮不属于我的主要组件的唯一原因是它们位于DOM中的其他位置。
在这种情况下,它实际上只是一个“扩展”组件,只能与“父”组件一起使用。我说“父母”,但在DOM中是兄弟姐妹-随便叫它。
就像我说的那样,它甚至不必是一个完整的组件,就我而言,它只是一个<button>(但它可以是一个组件)。
@Directive({
selector: '[ytPlayerPlayButton]'
})
export class YoutubePlayerPlayButtonDirective {
_player: YoutubePlayerComponent;
@Input('ytPlayerVideo')
private set player(value: YoutubePlayerComponent) {
this._player = value;
}
@HostListener('click') click() {
this._player.play();
}
constructor(private elementRef: ElementRef) {
// the button itself
}
}
Run Code Online (Sandbox Code Playgroud)
在的HTML中ProductPage.component,youtube-player显然是包装Youtube API的组件在哪里。
<youtube-player #technologyVideo videoId='NuU74nesR5A'></youtube-player>
... lots more DOM ...
<button class="play-button"
ytPlayerPlayButton
[ytPlayerVideo]="technologyVideo">Play</button>
Run Code Online (Sandbox Code Playgroud)
该指令为我提供了一切,而我不必在HTML中声明(click)事件。
因此,该指令可以很好地连接到视频播放器,而不必参与ProductPage调解器。
这是我第一次真正执行此操作,因此尚不确定在更复杂的情况下它的可伸缩性。为此,尽管我很高兴,但它却使我的HTML变得简单,而所有事情的职责却截然不同。
对于这个问题,共享服务是一个很好的解决方案。如果您也想存储一些活动信息,您可以将共享服务添加到您的主模块 (app.module) 提供程序列表中。
@NgModule({
imports: [
...
],
bootstrap: [
AppComponent
],
declarations: [
AppComponent,
],
providers: [
SharedService,
...
]
});
Run Code Online (Sandbox Code Playgroud)
然后你可以直接将它提供给你的组件,
constructor(private sharedService: SharedService)
Run Code Online (Sandbox Code Playgroud)
使用共享服务,您可以使用函数,也可以创建一个主题来一次更新多个位置。
@Injectable()
export class SharedService {
public clickedItemInformation: Subject<string> = new Subject();
}
Run Code Online (Sandbox Code Playgroud)
在您的列表组件中,您可以发布点击的项目信息,
this.sharedService.clikedItemInformation.next("something");
Run Code Online (Sandbox Code Playgroud)
然后您可以在详细信息组件中获取此信息:
this.sharedService.clikedItemInformation.subscribe((information) => {
// do something
});
Run Code Online (Sandbox Code Playgroud)
显然,列出组件共享的数据可以是任何东西。希望这可以帮助。
我很惊讶没有更多关于组件通信的信息<=> 考虑 angualr2 的本教程
对于同级组件通信,我建议使用sharedService. 不过,还有其他选项可用。
import {Component,bind} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS} from 'angular2/http';
import {NameService} from 'src/nameService';
import {TheContent} from 'src/content';
import {Navbar} from 'src/nav';
@Component({
selector: 'app',
directives: [TheContent,Navbar],
providers: [NameService],
template: '<navbar></navbar><thecontent></thecontent>'
})
export class App {
constructor() {
console.log('App started');
}
}
bootstrap(App,[]);
Run Code Online (Sandbox Code Playgroud)
请参阅顶部的链接以获取更多代码。
编辑:这是一个非常小的演示。您已经提到您已经尝试过sharedService. 因此,请考虑 angualr2 的本教程以获取更多信息。
| 归档时间: |
|
| 查看次数: |
82481 次 |
| 最近记录: |