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
考虑以下简单的 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