从"角度"组件中删除"输出"属性值



我想到了一个实验,这个实验源于我有时需要为我的Angular组件的Output添加和删除函数的情况。这是的例子

父组件将只包含子组件<my-component>的输出函数。

ParentComponent

class ParentComponent{
myOutputFunction = null;
setOutputFunction() {
this.myOutputFunction = () => {
// do something
};
}
removeOutputFunction() {
this.myOutputFunction = null;
}
}

ParentComponent模板

<my-component (someOutput)="myOutputFunction($event)"><my-component>

子组件MyComponent将在内部具有输出someOutput。这也将成为一个问题,即如何检测父母何时决定进行removeOutputFunction(),并可能订阅该事件并对其做出反应

MyComponent子组件

class MyComponent {
@Output() someOutput = new EventEmitter();
ngOnInit(): void {
// At this point we can see if there are any observers to someOutput
if(this.someOutput.observers.length > 0) {
console.log('YEY we have a set output method from ParentComponent to MyComponent`s attribute');
} else {
console.log('We have no attribute defined');
}
}
}

ngOnInit()中,我们可以检查是否对(someOutput)="myOutputFunction($event)"进行了编码。

所以,结论。有没有办法监听(订阅(someOutput从父级() => // do something值到null值的变化。

当我记录this.someOutput.observers时,我得到订阅服务器的数组。我可以用this.someOutput作为EventEmitter来达到这个实验的目的吗?

感谢

您不能动态删除输出属性,但我认为这个解决方案可以帮助您。

如果要设置从父组件到子组件的值,则应在子组件中使用@Input

@Output用于从子节点向父节点通知某些内容。

解决方案1

如果希望子组件仅在父组件具有函数时发出值,请在有人在侦听时告知子组件。

假设您的发射值为string类型

子组件

class MyComponent {
@Output() someOutput: EventEmitter<string> = new EventEmitter();
@Input() isParentListening = false;
ngOnInit(): void {
if (this.isParentListening) {
// Parent wants to receive data
this.someOutput.emit("Yay! Parent is listening");
} else {
// Parent is not listening
console.log("My parent doesn't take care of me :(");
}
}
}

父组件

<my-component
[isParentListening]="listenChildComponent"
(someOutput)="myOutputFunction($event)"
></my-component>
class ParentComponent {
listenChildComponent = true;
myOutputFunction = (value: string) => {
// do something
};
}

解决方案2

另一个解决方案是让子组件保持干净,并且不知道这个逻辑,由父组件决定是否必须执行某些操作。

子组件

class MyComponent {
@Output() someOutput: EventEmitter<string> = new EventEmitter();
ngOnInit(): void {
// Output always as if someone were listening
this.someOutput.emit("Yay! Someone is listening (I hope)");
}
}

父组件

当输出事件发生时,父级根本不实现任何逻辑。

<my-component (someOutput)="()=>{}"></my-component>
class ParentComponent {}

一旦使用模板,就无法通过观察者的数量来推断任何内容。即使你做到了:

<my-component (someOutput)="myOutputFunction"><my-component>

myOutputFunction为空的情况下,观察者的数量仍然是1。

您可以通过使用ViewChild有条件地设置观察器的编程方法(而不是建议的方法,请参阅下面的原因*(来部分实现这一点:

@ViewChild(MyComponent, { static: true }) comp: MyComponent;
myOutputFunction = null;
setOutputFunction() {
this.myOutputFunction = () => {
console.log('something');
};
this.comp.someOutput.subscribe(this.myOutputFunction);
}

请参阅演示:https://stackblitz.com/edit/angular-output-programmatic

然而,我认为你做这件事的方式不对。似乎您希望子组件(有条件地(在有人在听的情况下产生一些结果。

  • 使用EventEmitter来推断这是错误的;如果您希望子组件中的行为依赖于myOutputFunction,请将@Input((传递给子组件-最简单的方法是,传递myOutputFunction本身并让子组件调用它。或者:
  • 一般来说,这听起来像是一个可观察的用例:如果(并且只有当(有人订阅了它,就应该产生一些东西。消费者是父母,生产者是孩子。以救援为准
  • 这样的模式听起来与组件无关;考虑将可观察的/主题放在服务中

你可能已经意识到了这一切,所以我把它留在:不,不要把逻辑建立在EventEmitter的观察者的基础上*即使你采用程序化的方法,你也打破了一些基本的抽象;子组件的正确使用和行为需要消费者对子组件逻辑有复杂的了解。

为什么不使用Input?

class MyComponent {
@Input() func = null;
ngOnInit(): void {
if (func)
func();
else
console.log("I'm child")
}
}

在您的父中

<app-child [func]="functionInParent"></app-child>
functionInParent()
{
console.log("function in parent") 
}
//OR
<app-child></app-child>

这是一个非常有趣的想法。但为了确保您得到了正确的时间,您应该收听"newListener"事件并在那里执行逻辑。检查此链接作为参考https://nodejs.org/api/events.html#events_event_newlistener

....
this.someOutput.once('newListener', (event, listener) => {
... // you have a listener
})
...

最新更新