首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何定义带有角元素的自定义元素方法

如何定义带有角元素的自定义元素方法
EN

Stack Overflow用户
提问于 2020-12-01 08:15:38
回答 1查看 655关注 0票数 3

我们的Angular-Elements any组件应该有两个方法openModal()closeModal(),它们可以作为自定义元素React、Vue或任何其他库来更改可见性状态。

这种简单的javascript使用应该是可能的:

代码语言: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应该设置为truefalse,以便模板可以使用它。

代码语言:javascript
复制
@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?

  • Why来装饰我们的公共组件方法(openModal()closeModal() ),即使我们不使用它们,我们需要用@Input来装饰visible-Flag?这非常糟糕,因为我们公开了内部状态,而且它看起来是一种有效的方法??

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-01 09:16:56

@Input()s是为属性而不是函数设计的。对于用例,您可以简单地使用getter并在那里返回函数。

至于visible状态没有改变:它确实改变了(只需在更改后与console.log检查)。但是,这种变化并不是由角的变化检测来检测的,因为调用是从角度上下文中产生的。例如,在使用setTimeout更改值时,您会遇到同样的问题。为了解决这个问题,将NgZone注入到组件中,并使用this.zone.run对变化进行角度检测。

代码语言:javascript
复制
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

代码语言:javascript
复制
// 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(),这样它就可以在宿主应用程序中绑定。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65086867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档