网站搜索

typescript - 基于 Prop 值在 StencilJS 中的动态事件名称


我正在尝试使用 StencilJS 创建一个通用滑块组件。我的想法是将滑块 ID 作为 prop 传递,然后在滑块变化时将该 prop 用作事件名称。

问题是监听器没有捕捉到用 prop 名称发出的动态事件。我认为这可能与组件的生命周期有关,但我不确定。有何想法吗?

export class ParentComponent{

    @Listen('slider_A')
    onSliderValueChangeA(){
        console.log('event A') //not logging on slider change
    }

    @Listen('slider_B')
    onSliderValueChangeB(){
        console.log('event B') //not logging on slider change
    }

    @Listen('slider_C')
    onSliderValueChangeC(){
        console.log('event C')//not logging on slider change
    }

    render(){
        return (
            <div class='container'>
                <slider-input slider_id={'slider_A'} slider_title={'S1'} ></slider-input>
                <slider-input slider_id={'slider_B'} slider_title={'S2'} ></slider-input>
                <slider-input slider_id={'slider_C'} slider_title={'S3'} ></slider-input>
            </div>
        );
    }
}

Here is the slider component...

@Component({
    tag: 'slider-input',
    styleUrl: 'slider-input.scss',
    shadow: true
})

export class Slider{
    @Prop() slider_id: string;


    @Event({
        eventName: this.slider_id,
    }) on_slider_value_change: EventEmitter<null>;


    onValueChange(change){
        this.slider_value = change.value;
        this.on_slider_value_change.emit()
    }
.
.
.

答案#1

我认为更好的方法是将滑块的 ID 作为事件数据/细节发出,不过无论如何……

据我所知,监听器应该可以工作,但 @Event 装饰器可能不行。你可以尝试手动创建事件,使用 dispatchEvent 和 CustomEvent。

export class MySlider {
  @Element() host: HTMLMySliderElement;

  onValueChange(change) {
    this.slider_value = change.value;

    this.host.dispatchEvent(new CustomEvent(this.slider_id));
  }

  // ...
}

答案#2

据我所知,在 Stencil 中动态事件名称是不可能的,可能是因为事件名称在组件加载之前就被解析了。

相反,你可以直接将监听器附加到元素上:

export class Slider {
    @Prop() slider_id: string;

    @Event() valueChange: EventEmitter<null>;

    onValueChange(change){
        this.slider_value = change.value;
        this.valueChange.emit()
    }
]
export class ParentComponent{

    onSliderValueChange(id: string){
        console.log('event', id)
    }

    render(){
        return (
            <div class='container'>
                <slider-input slider_id={'slider_A'} onValueChange={() => this.onSliderValueChange('A')} slider_title={'S1'} ></slider-input>
                <slider-input slider_id={'slider_B'} onValueChange={() => this.onSliderValueChange('B')} slider_title={'S2'} ></slider-input>
                <slider-input slider_id={'slider_C'} onValueChange={() => this.onSliderValueChange('C')} slider_title={'S3'} ></slider-input>
            </div>
        );
    }
}

或者你可以手动添加监听器:

@Element() el: HTMLElement;

this.el.querySelector('slider-input').addEventListener('valueChange', e => {
  switch(e.currentTarget.slider_id) {
    case 'slider_A':
      console.log('event A');
      break;
    case 'slider_B':
      console.log('event B');
      break;
  }
});

// or

this.el.querySelector('slider-input[slider_id=slider_A]')
  .addEventListener('valueChange', () => console.log('event A');