我有两个组件,如下所示,我想从另一个组件调用一个函数。这两个组件都包含在第三个父组件 using 指令中。
构成部分1:
@component(
selector:'com1'
)
export class com1{
function1(){...}
}
@component(
selector:'com2'
)
export class com2{
function2(){...
// i want to call function 1 from com1 here
}
}
我尝试过使用@input
和@output
但我不知道如何使用它以及如何调用该函数,任何人都可以帮忙吗?
ngOnInit() {}
public testCall(){
alert("I am here..");
}
import { oneComponent } from '../one.component';
@Component({
providers:[oneComponent ],
selector: 'app-two',
templateUrl: ...
}
constructor(private comp: oneComponent ) { }
public callMe(): void {
this.comp.testCall();
}
组件两个 html 文件
<button (click)="callMe()">click</button>
如果 com1 和 com2 是兄弟姐妹,您可以使用
@component({
selector:'com1',
})
export class com1{
function1(){...}
}
com2使用< code>EventEmitter发出一个事件
@component({
selector:'com2',
template: `<button (click)="function2()">click</button>`
)
export class com2{
@Output() myEvent = new EventEmitter();
function2(){...
this.myEvent.emit(null)
}
}
这里,父组件添加了一个事件绑定来侦听< code>myEvent事件,然后在此类事件发生时调用< code>com1.function1()。< code>#com1是一个模板变量,允许从模板中的其他地方引用该元素。我们用它来使< code>function1()成为< code>com2的< code>myEvent的事件处理程序:
@component({
selector:'parent',
template: `<com1 #com1></com1><com2 (myEvent)="com1.function1()"></com2>`
)
export class com2{
}
关于组件间通信的其他选项,请参见组件交互
首先,您需要了解组件之间的关系。然后,您可以选择正确的通信方式。我将尝试解释我在实践中知道并使用的所有方法,以进行组件之间的通信。
组件之间可以有什么样的关系?
1. 家长
通过输入共享数据
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
<child-component [childProperty]="parentProperty"></child-component>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent{
parentProperty = "I come from parent"
constructor() { }
}
child.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'child-component',
template: `
Hi {{ childProperty }}
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
@Input() childProperty: string;
constructor() { }
}
这是一个非常简单的方法。它很容易使用。我们还可以使用ngOnChanges捕捉子组件中的数据变化。
但不要忘记,如果我们使用一个对象作为数据并更改该对象的参数,对它的引用将不会更改。因此,如果我们想在子组件中接收修改后的对象,它必须是不可变的。
通过ViewChild共享数据
ViewChild允许将一个组件注入到另一个组件中,使父组件可以访问其属性和功能。但是,有一点需要注意,在视图初始化之前,< code>child是不可用的。这意味着我们需要实现AfterViewInit生命周期钩子来接收来自孩子的数据。
parent.component.ts
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from "../child/child.component";
@Component({
selector: 'parent-component',
template: `
Message: {{ message }}
<child-compnent></child-compnent>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child;
constructor() { }
message:string;
ngAfterViewInit() {
this.message = this.child.message
}
}
child.component.ts
import { Component} from '@angular/core';
@Component({
selector: 'child-component',
template: `
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message = 'Hello!';
constructor() { }
}
通过 Output() 和 EventEmitter 共享数据
共享数据的另一种方法是从子级发出数据,该数据可以由父级列出。当您想要共享在按钮单击、表单条目和其他用户事件等事件上发生的数据更改时,此方法是理想的选择。
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
Message: {{message}}
<child-component (messageEvent)="receiveMessage($event)"></child-component>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message:string;
receiveMessage($event) {
this.message = $event
}
}
child.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-component',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message: string = "Hello!"
@Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
3. 兄弟姐妹
孩子
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
Message: {{message}}
<child-one-component (messageEvent)="receiveMessage($event)"></child1-component>
<child-two-component [childMessage]="message"></child2-component>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message: string;
receiveMessage($event) {
this.message = $event
}
}
child-one .组件. ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-one-component',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child-one.component.css']
})
export class ChildOneComponent {
message: string = "Hello!"
@Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
child-two.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'child-two-component',
template: `
{{ message }}
`,
styleUrls: ['./child-two.component.css']
})
export class ChildTwoComponent {
@Input() childMessage: string;
constructor() { }
}
4.不相关组件
我下面描述的所有方法都可以用于组件之间关系的所有上述选项。但各有利弊。
与服务共享数据
当在缺少直接连接的组件之间传递数据时,比如兄弟、孙等,应该使用共享服务。当您有应该总是同步的数据时,我发现RxJS BehaviorSubject在这种情况下非常有用。
data.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
}
第一.ts组件
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'first-componennt',
template: `
{{message}}
`,
styleUrls: ['./first.component.css']
})
export class FirstComponent implements OnInit {
message:string;
constructor(private data: DataService) {
// The approach in Angular 6 is to declare in constructor
this.data.currentMessage.subscribe(message => this.message = message);
}
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
}
第二个组件是.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'second-component',
template: `
{{message}}
<button (click)="newMessage()">New Message</button>
`,
styleUrls: ['./second.component.css']
})
export class SecondComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
newMessage() {
this.data.changeMessage("Hello from Second Component")
}
}
与路径共享数据
有时,您不仅需要在组件之间传递简单的数据,还需要保存页面的某些状态。例如,我们希望在在线市场中保存一些过滤器,然后复制此链接并发送给朋友。我们希望它以与我们相同的状态打开页面。第一种可能也是最快的方法是使用查询参数。
查询参数看起来更像< code>/people?id=其中< code>id可以等于任何值,并且您可以拥有任意多个参数。查询参数将由&字符分隔。
import {Component} from "@angular/core";
import {Router, NavigationExtras} from "@angular/router";
@Component({
selector: "page1",
template: `
<button (click)="onTap()">Navigate to page2</button>
`,
})
export class Page1Component {
public constructor(private router: Router) { }
public onTap() {
let navigationExtras: NavigationExtras = {
queryParams: {
"firstname": "Nic",
"lastname": "Raboy"
}
};
this.router.navigate(["page2"], navigationExtras);
}
}
在接收页面中,您将接收以下查询参数:
import {Component} from "@angular/core";
import {ActivatedRoute} from "@angular/router";
@Component({
selector: "page2",
template: `
<span>{{firstname}}</span>
<span>{{lastname}}</span>
`,
})
export class Page2Component {
firstname: string;
lastname: string;
public constructor(private route: ActivatedRoute) {
this.route.queryParams.subscribe(params => {
this.firstname = params["firstname"];
this.lastname = params["lastname"];
});
}
}
NgRx
最后一种方式更复杂,但功能更强大,那就是使用NgRx。此库不用于数据共享;这是一个强大的状态管理库。我不能用一个简短的例子来解释如何使用它,但是你可以去官方网站阅读相关文档。
对我来说,NgRx Store解决了多个问题。例如,当您必须处理可观察数据时,以及当不同组件分担一些可观察数据的责任时,存储动作和缩减器确保数据修改总是以“正确的方式”执行。
它还为HTTP请求缓存提供了一个可靠的解决方案。您将能够存储请求和它们的响应,这样您就可以验证您发出的请求还没有存储的响应。
问题内容: 抱歉,我确定一个基本问题,但似乎无法弄清楚。 说我有这个程序,文件名为: 如何在另一个程序中调用它?我试过了: 而不是“ hello world”,我得到了……过去我通过将第一个文件设为类来做到这一点,但我想知道如何正确导入该函数?如果有帮助,我会在我的真实文件中打印字典 问题答案: 您需要打印调用函数的结果,而不是函数本身: 另外,您可以省略子句,而不是: 如果更方便,也可以使用:
问题内容: 我有一个包含一个按钮的标题组件,并且我希望该按钮在单击时显示另一个组件(模式页面)。 我可以做这样的事情: 这是我的标头组件: 这是我的模态页面组件,单击其他组件上的按钮时应显示该组件页面: 用于模态的库:https : //github.com/marcio/react-skylight 问题答案: 更像这样: 确保在子组件上公开一个方法: 基本上,这是在将SkyLight的方法包装
我有一个异步函数getIdentByInfo,在控制台中,如果我将它记录在这个函数中,就会得到正确的输出。当我在另一个组件中调用它时,它就不工作了,我只得到“未定义”。我知道这与蜂群同步和承诺有关,但我不知道如何解决我的问题。我需要在另一个组件中填充来自http请求的属性的模型类,以便将它们发送到另一个服务
问题内容: 是否可以从另一个(在同一类中,而不是在子类中)调用构造函数?如果是,怎么办?调用另一个构造函数的最佳方法是什么(如果有几种方法可以做到)? 问题答案: 对的,这是可能的: 要链接到特定的超类构造函数而不是同一类中的构造函数,请使用代替。注意,你只能链接到一个构造函数,它必须是构造函数主体中的第一条语句。
问题内容: 我想调用一个在second.js文件的first.js文件中定义的函数。这两个文件都在HTML文件中定义,例如: 我想打电话给在定义中。根据我的搜索结果,答案是首先定义是否可以,但是根据我的测试,我没有找到任何方法。 这是我的代码: 问题答案: 除非在同一文件中定义了该函数,或者在尝试调用该函数之前已加载了该函数,否则无法调用该函数。 除非函数的范围与尝试调用该函数的范围相同或更大,否
我不明白为什么下面的代码会打印两次。我以为应该是个人和学生。当通过“a”对象调用printPerson()内部的getInfo()时,为什么要调用Person类内部的一个,为什么不调用Student类中的一个?提前谢谢。