在vue3中使用`window.addEventListener` 监听iframe事件,多次触发vue3中的emits的自定义事件问题

968 阅读3分钟

在vue3中使用window.addEventListener 监听iframe事件,多次触发vue3中的emits的自定义事件问题

  • 事件的起因
  • 如何发现
  • 如何解决

1.事件的起因

  • 在写项目中需要监听iframe发送的事件并传递参数进行一些列操作,我用到了三层组件第一层就是爷爷组件第二层就是父亲组件,第三层就是孙子组件孙子组件进行window.addEventListener监听然后通过vue3中的emits进行发送一个事件给父亲组件,再由父亲组件发送一个事件给爷爷组件,由此问题就产生了,每次使用window.addEventListener进行监听发送事件的时候,第二次监听会重复之前的监听事件,也就是说,你监听了多少次那么爷爷组件这边接受的事件就会重复执行多少次。

  • 说了这么多废话不知道列为看懂了没有,下面通过一张图来解释一下。

    • 大概的意思就是这种

2.如何发现

  • 当需要通过孙子组件传递出的数据到爷爷组件中调用接口的时候,并且传递的数据只能调用一次的时候我发现他会重复的调用多次,再次打印调试的时候同样就会出现多次重复打印 如果你多次监听会重复执行多次。
  • 后来我怀疑是不是vue3内部对嵌套组件深层组件通过emits发送的事件会重复触发,后来我测试一下并没有,一共有两个怀疑的地方,一个地方被排除了,当然就是另外一个window.addEventListener 这个api身上了。

3.如何解决

  • 第一种解决的方法

    • 通过使用vue3中的watchapi虽然会重复执行但每次执行传递的参数都是相同的,所以我们可以通过watch api来进行处理但没有解决根本问题。
  • 第二种解决的方法

    • window.addEventListener api一共有三个参数,window.addEventListener 可以自己看看,第三个参数是一个Boolean值,为true会以事件冒泡的方式触发。为false的时候就以事件捕获的方式触发listener,而冒泡不会触发listener。

4、总结

  • 最后我们需要做的就是当组件销毁的时候将监听remove掉就可以了,对于这种孙子组件爷爷组件传递数据的方式过于繁琐了,不建议各位这样子做可以使用 provide和inject来触发使用如下:

    1.父传孙数据:provide
    ​
    2.子孙得到数据:inject
    ​
    父传孙子  
    ​
    父组件:
    import { ref, provide } from 'vue'
     setup() {
        // 直接把数据传递出去给孙子传  参数一:规定一个爷孙之间的变量名   参数二 要传的值  可以是函数
        provide('sendInfo', 1000)
      }
    孙子组件:
    // 注入 接到爷爷给的数据 然后就可以用了
    import { inject } from 'vue'
     setup() {
       const data= inject('sendInfo')
      }
    ​
    孙子向爷传数据:
    ​
    孙子:
    // 注入 接到爷爷给的通信函数
    import { inject } from 'vue'
     setup() {
        // 接收爷爷的空的函数
        const sendGrandson = inject('sendHandle');
        // 触发send函数的时候 向爷爷通信,给爷爷传递数据
        const send = function() {
          sendGrandson(6000)
        }
        return { send }
      }
    ​
    爷爷:
    import { ref, provide } from 'vue'
     setup() {
         // 给孙子传一个函数  当孙子那里触发向爷爷通信 就会 触发sendGrandson 
        const sendGrandson = function(value) {
          console.log('孙子传值给我', value)
        }
        provide('sendHandle', sendGrandson)
      }
    
  • 或者使用eventBus来进行事件的监听,如果监听比较多的话还是不建议使用这个eventBus比较消耗内存和响应速度。