在vue3中使用window.addEventListener
监听iframe事件,多次触发vue3中的emits的自定义事件问题
- 事件的起因
- 如何发现
- 如何解决
1.事件的起因
-
在写项目中需要监听iframe发送的事件并传递参数进行一些列操作,我用到了三层组件第一层就是爷爷组件第二层就是父亲组件,第三层就是孙子组件由孙子组件进行
window.addEventListener
监听然后通过vue3中的emits进行发送一个事件给父亲组件,再由父亲组件发送一个事件给爷爷组件,由此问题就产生了,每次使用window.addEventListener
进行监听发送事件的时候,第二次监听会重复之前的监听事件,也就是说,你监听了多少次那么爷爷组件这边接受的事件就会重复执行多少次。 -
说了这么多废话不知道列为看懂了没有,下面通过一张图来解释一下。
2.如何发现
- 当需要通过孙子组件传递出的数据到爷爷组件中调用接口的时候,并且传递的数据只能调用一次的时候我发现他会重复的调用多次,再次打印调试的时候同样就会出现多次 如果你多次监听会重复执行多次。
- 后来我怀疑是不是vue3内部对嵌套组件深层组件通过emits发送的事件会重复触发,后来我测试一下并没有,一共有两个怀疑的地方,一个地方被排除了,当然就是另外一个
window.addEventListener
这个api身上了。
3.如何解决
-
第一种解决的方法
- 通过使用vue3中的
watch
api虽然会重复执行但每次执行传递的参数都是相同的,所以我们可以通过watch
api来进行处理但没有解决根本问题。
- 通过使用vue3中的
-
第二种解决的方法
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比较消耗内存和响应速度。