我们的Angular-Elements any组件应该有两个方法openModal()和closeModal(),它们可以作为自定义元素React、Vue或任何其他库来更改可见性状态。
这种简单的javascript使用应该是可能的:
<my-modal id="modal"></my-modal>
<button id="openModal" onclick="openModal()">open</button>
<button id="closeModal" onclick="closeModal()">close</button>
<script>
const modal = document.getElementById("modal");
function openModal() {
modal.openModal();
}
function closeModal() {
modal.closeModal();
}
</script>内部属性visible应该设置为true或false,以便模板可以使用它。
@Component({
selector: 'my-modal',
template: `<p>Attribute visible: {{visible}}</p>`,
styles: []
})
export class MyModalComponent {
// Without `@Input` changes to the variable within `openModal()`
// and `closeModal()` will not effect the components state!
visible = false;
// Without the `@Input()` here, angular-elements will not
// map the `openModal()` to our custom-element.
@Input()
public openModal(): void {
console.log("Open Modal")
this.visible = true;
}
@Input()
public closeModal(): void {
console.log("Close Modal")
this.visible = false;
}
}问题:
为什么我们需要用Input-Parameter?
openModal()和closeModal() ),即使我们不使用它们,我们需要用@Input来装饰visible-Flag?这非常糟糕,因为我们公开了内部状态,而且它看起来是一种有效的方法??。
发布于 2020-12-01 09:16:56
@Input()s是为属性而不是函数设计的。对于用例,您可以简单地使用getter并在那里返回函数。
至于visible状态没有改变:它确实改变了(只需在更改后与console.log检查)。但是,这种变化并不是由角的变化检测来检测的,因为调用是从角度上下文中产生的。例如,在使用setTimeout更改值时,您会遇到同样的问题。为了解决这个问题,将NgZone注入到组件中,并使用this.zone.run对变化进行角度检测。
import { Component, Input, NgZone } from '@angular/core';
@Component({
selector: 'app-root',
template: `<p>Attribute visible: {{visible}}</p>`,
styles: []
})
export class MyModalComponent {
visible = false;
// use property getters to return functions
@Input()
get openModal(): () => void {
return () => {
// make change in angular's context so changes are detected by angular
this.zone.run(() => this.visible = true);
}
}
@Input()
get closeModal(): () => void {
return () => {
// make change in angular's context so changes are detected by angular
this.zone.run(() => this.visible = false);
}
}
// inject NgZone
constructor(private zone: NgZone) { }
}或者,您可能希望使用OnPush更改检测。您将使用主题和可观察性以及在这个包中实现的“推送”管道(异步管道的变体):https://github.com/rx-angular/rx-angular
// in app.module.ts
import {TemplateModule} from '@rx-angular/template';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
TemplateModule // import module
// ...
import { Component, Input, NgZone } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'app-root',
// use observable with push pipe
template: `<p>Attribute visible: {{visible$ | push}}</p>`,
// use OnPush change detection
changeDetection: ChangeDetectionStrategy.OnPush,
styles: []
})
export class AppComponent {
// use subjects/observables
visibleSubject = new BehaviorSubject<boolean>(false);
visible$ = this.visibleSubject.asObservable();
@Input()
get openModal(): () => void {
return () => {
this.visibleSubject.next(true);
}
}
@Input()
get closeModal(): () => void {
return () => {
this.visibleSubject.next(false);
}
}
}当然,如果它像更改布尔标志一样简单,那么您最好将该属性公开为@Input(),这样它就可以在宿主应用程序中绑定。
https://stackoverflow.com/questions/65086867
复制相似问题