Stencil.js - 事件监听器的解释

Stencil.js - explanation of event listeners

考虑以下简单的 input 组件:

import { Component, VNode, h, Prop, Host } from '@stencil/core'

@Component({
  tag: 'my-input',
})
export class MyInput {
  @Prop() inputId!: string
  @Prop() label!: string
  @Prop() value: string

  render(): VNode {
    return (
      <Host>
        <label htmlFor={this.inputId}>{this.label}</label>
        <input type="text" id={this.inputId} value={this.value}  />
      </Host>
    )
  }
}

使用几个事件侦听器呈现 <my-input> 组件的父组件:

import { Component, h, VNode } from '@stencil/core'

@Component({
  tag: 'my-page',
})
export class MyPage {
  private handleInput = (ev: Event) => {
    // this works
    console.log('handle input')
  }

  private handleFocus = (ev: Event) => {
    // this doesn't work
    console.log('handle focus')
  }

  private handleClick = (ev: Event) => {
    // this works
    console.log('handle click')
  }

  private handleBlur = (ev: Event) => {
    // this doesn't work
    console.log('handle blur')
  }

  render(): VNode {
    return (
      <my-input
        label="Label"
        inputId="testId"
        onInput={this.handleInput}
        onFocus={this.handleFocus}
        onClick={this.handleClick}
        onBlur={this.handleBlur}
      />
    )
  }
}

有人能给我解释一下吗,怎么可能有些听众真的工作而其他人不工作?

焦点和模糊事件处理程序不触发的原因是您将侦听器附加到 my-input 元素而不是实际的 input 元素。这意味着只有气泡事件的侦听器会触发(点击、输入),其余事件(焦点、模糊)不会。

启用这些非冒泡事件的一种方法是代理它们:

export class MyInput {
  @Event() myFocus: EventEmitter<FocusEvent>;

  render() {
    return (
      <Host>
        <label htmlFor={this.inputId}>{this.label}</label>
        <input type="text" id={this.inputId} value={this.value} onFocus={e => this.myFocus.emit(e)} />
      </Host>
    )
  }
}

在这里,我将 focus 事件处理程序附加到 input 并触发自定义 myFocus 事件,您可以从组件外部侦听该事件。您可能还想通过将装饰器更改为 @Listen({ bubbles: false }) myFocus;

来阻止这些事件冒泡

Ionic Framework(与 Stencil 由同一个人制作)也是这样做的,参见 https://github.com/ionic-team/ionic-framework/blob/master/core/src/components/input/input.tsx#L220