如何在Vue中实现事件监听的叠加效果(事件重复时)?

在使用vue的时候,遇到了定义原生事件与@xxx事件重合时,@xxx事件绑定不上的情况(感觉是被覆盖了)。具体代码如下

this.generateDiagram()
          const inputCheck = e => {
            e.target.value = e.target.value.replace(/[^\d.-]/, '')
            e.target.value = e.target.value.replace(/\.+/, '.')
            e.target.value = e.target.value.replace(
              /(\d)(\.\d{0,3})\d*/,
              '$1$2'
            )
            e.stopPropagation()
          }

          //todo:セレクトのinputに影響を及ぼすかも?
          document.querySelectorAll('input').forEach(item => {
            item.addEventListener('input', e => {
              e.target.value = e.target.value.replace(/^0/, '')
              inputCheck(e)
            })
          })

这是原生监听事件写的,监听画面上所有input框input事件的代码。
但是在特定的输入框中我又想监听特定的input事件,于是有如下代码

 <v-text-field
                                      :label="expensesInfoList[index+i-1].text"
                                      density="compact"
                                      variant="outlined"
                                      color="primary"
                                      :suffix="expensesInfoList[index+i-1].suffix"
                                      v-model.number="datas[expensesInfoList[index+i-1].key]"
                                      :disabled="expensesInfoList[index+i-1].disabled"
                                      v-if="index+i-1 < expensesInfoList.length"
                                      @input="expensesInfoList[index+i-1].onInput?expensesInfoList[index+i-1].onInput(expensesInfoList[index+i-1].onInputParameter):null"
                                    >
                                    </v-text-field>

其中有绑定input事件的代码,内容是动态绑定的写得比较绕,但是没有错,@input换成@click的话是可以触发的。
问题就是,有什么办法可以让两处地方对input事件加的监听函数叠加起来吗?
而不是其中一个覆盖掉另外一个想做的事。

我试过把原生的input监听那段删了,@input绑定的事件就好使了。
我希望可以两个地方写的都好使,得到他们叠加的效果

阅读 829
avatarAI BotBETA

在Vue中,当你在组件上同时使用了内联事件监听器(如@input)和原生的addEventListener,可能会出现事件监听冲突的问题。这是因为Vue的事件监听器实际上也是通过addEventListener实现的,所以当你手动添加监听器时,可能会覆盖或干扰Vue的默认监听器。

为了解决这个问题,你可以尝试以下方法来实现事件监听的叠加效果:

  1. 使用Vue的自定义指令:Vue允许你注册自定义指令,你可以在自定义指令中处理事件,并在需要时调用原始的监听器。这样,你可以将原生监听器和Vue的监听器结合起来,实现叠加效果。
Vue.directive('double-input', {
  bind(el, binding, vnode) {
    const originalInputHandler = el.oninput;
    el.oninput = function(event) {
      // 在这里调用你的原生监听器逻辑
      inputCheck(event);
      
      // 如果存在原始的监听器,也调用它
      if (originalInputHandler) {
        originalInputHandler.call(el, event);
      }
      
      // 调用Vue的监听器逻辑
      vnode.context[binding.expression](event);
    };
  }
});

然后在你的模板中使用这个自定义指令:

<v-text-field
  @double-input="expensesInfoList[index+i-1].onInput?expensesInfoList[index+i-1].onInput(expensesInfoList[index+i-1].onInputParameter):null"
>
</v-text-field>
  1. 使用Vue的$listeners属性:Vue组件的$listeners属性包含了所有未被子组件识别的事件监听器。你可以利用这个属性来访问和处理这些监听器。

在你的组件中,你可以这样做:

export default {
  mounted() {
    const inputElements = document.querySelectorAll('input');
    inputElements.forEach(inputElement => {
      inputElement.addEventListener('input', this.handleInput);
    });
  },
  beforeDestroy() {
    const inputElements = document.querySelectorAll('input');
    inputElements.forEach(inputElement => {
      inputElement.removeEventListener('input', this.handleInput);
    });
  },
  methods: {
    handleInput(event) {
      // 在这里处理你的原生监听器逻辑
      inputCheck(event);
      
      // 调用Vue的监听器逻辑
      this.$emit('input', event);
    }
  }
};

这样,你的原生监听器逻辑和Vue的监听器逻辑都会被调用,实现了叠加效果。

请注意,以上方法只是提供了解决问题的思路,具体的实现可能需要根据你的代码结构和需求进行调整。

2 个回答

官方文档
image.png
叠加没问题,@唯一丶已经指出了是你把子标签的冒泡事件给禁止了没让事件向上冒泡

  1. 自定义组件的时间不是原生 DOM 事件,而是组件使用事件框架触发的
  2. 你在 input 标签里侦听 input 事件,然后 stopPropagation() 停止冒泡之后,自定义组件 v-text-field 就侦听不到 input 事件了,自然也无法再触发自己的事件
  3. 继而,你也就侦听不到自定义组件的事件了。
  4. 所以不要乱混代码。既然你用 Vue,就尽量在 Vue 里处理你的需求。你两边一起乱搞,很容易出问题,很难维护。
  5. 解决方案是统一处理你的功能,好好规划好好整合。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题