0

我有一个文本区域列表:

text-area.component.html

<!--suppress HtmlFormInputWithoutLabel -->
<textarea [ngClass]="generateTextAreaClass()" (keypress)="onKeyPress($event)">{{ value }}</textarea>

textarea 有一个keypress事件。

当我在其中一个文本区域中按下一个键时,它会触发keypress该组件的所有实例的事件。

结果,我触发了 5 个事件。这显然不代表我刚刚作为用户所做的操作。

{textareaSelector: ".app-utility-textarea-1-1", keypressType: "shift+enter"}
{textareaSelector: ".app-utility-textarea-1-1", keypressType: "shift+enter"}
{textareaSelector: ".app-utility-textarea-1-1", keypressType: "shift+enter"}
{textareaSelector: ".app-utility-textarea-1-1", keypressType: "shift+enter"}
{textareaSelector: ".app-utility-textarea-1-1", keypressType: "shift+enter"}

如何将事件限制为仅针对我当前正在输入的文本区域触发,以便仅触发一个事件?

@Component({
  selector: 'app-utility-textarea',
  templateUrl: './text-area.component.html',
  styleUrls: ['./text-area.component.scss']
})
export class TextAreaComponent implements AfterViewInit {

  constructor(private eventBus: EventBusService) {
  }

  @Input() value: string;
  @Input() id: string;
  public textAreaClassPrefix = 'app-utility-textarea';

  ...

  generateTextAreaClass(): string {
    return `${this.textAreaClassPrefix}-${this.id}`;
  }

  onKeyPress(event: KeyboardEvent) {
    event.stopPropagation();
    if (event.key === 'Enter' && event.shiftKey) {
      event.preventDefault();
      const textAreaKeyPressEvent: TextAreaKeyPressEvent = {
        textareaSelector: this.generateTextAreaClassCSSSelector(),
        keypressType: TextAreaKeyPressType.SHIFT_ENTER
      };
      this.eventBus.textAreaKeyPressSubject$.next(textAreaKeyPressEvent);
    }
  }
}

事件总线.service.ts

@Injectable()
export class EventBusService {

  public navbarSubject$ = new BehaviorSubject(DashboardNavbarEvent.SIDEBAR_MENU_CLOSED);
  public textAreaKeyPressSubject$ = new Subject<TextAreaKeyPressEvent>();

  constructor() {
  }

}

订阅者.component.ts

@Component({
  selector: 'app-subscriber',
  templateUrl: './subscriber.component.html',
  styleUrls: ['./subscriber.component.scss']
})
export class SubscriberComponent implements OnInit {

  @Input() public block: any;
  @Input() public index: number;

  constructor(private eventBus: EventBusService) {
  }

  ngOnInit() {
    this.eventBus.textAreaKeyPressSubject$.subscribe((event: TextAreaKeyPressEvent) => {
      console.log(event);
    });
  }

}
4

2 回答 2

0

您正在使用来自subject的主题:

什么是主题?RxJS Subject 是一种特殊类型的 Observable,它允许将值多播到多个 Observer。虽然普通的 Observable 是单播的(每个订阅的 Observer 都拥有 Observable 的独立执行),但 Subjects 是多播的。

你正在通过 next in 发出一个事件:

this.eventBus.textAreaKeyPressSubject$.next(textAreaKeyPressEvent);

所以基本上你正在向多播订阅者发送一些东西,所以正如你所看到的,事件是从正确的一个文本区域触发的,但是你正在将事件传播给其他订阅者。关键是您想要一对一订阅,而不是一对多。希望这有帮助

于 2019-05-28T10:59:19.823 回答
0

原来这是一个设计问题。我正在订阅textAreaKeyPressSubject$内部另一个有 5 个实例的组件。每个实例最终都订阅了textAreaKeyPressSubject$on init 并记录了每个事件 1 次。

keypress事件仅textarea.component.ts在我输入的地方触发一次。

当我将此主题的订阅移至只有一个实例的父组件时,此问题已解决。

于 2019-05-28T10:49:59.723 回答