【问题标题】:Dynamic Event Names in StencilJS based on Prop valueStencilJS 中基于 Prop 值的动态事件名称
【发布时间】:2023-03-27 15:02:01
【问题描述】:

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

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

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()
    }
.
.
.

【问题讨论】:

    标签: typescript events dynamic stenciljs listen


    【解决方案1】:

    我认为更好的方法是将滑块的 ID 作为事件数据/详细信息发出,但无论如何...

    监听器应该可以正常工作,但 @Event 装饰器可能不会。您可以尝试使用 dispatchEventCustomEvent 手动创建事件。

    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');
      

      【讨论】:

      • 感谢您为我提供此解决方案。这种与通用输入组件的数据绑定是我正在处理的整个项目的一个关键方面,因此它非常重要,足以成为我的第一个堆栈溢出问题。我希望他们将来会添加动态事件名称。
      • @StevenWoerpel 我添加了更多选项。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 2019-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 2013-11-18
      相关资源
      最近更新 更多