关于vue中递归生成树形节点组件时,点击事件传递的问题

1,649 阅读1分钟

问题

之前在使用vue开发树形菜单组件时,遇到点击子节点会触发多次点击事件的问题,这里记录一下问题原因以及解决方法。

首先,有如下一份树形结构数据:

vue中递归生成树形节点组件.png

用vue组件简单写一个递归生成树形组件的示例:

父组件:Main.vue

父组件.png

子组件:Tree.vue

子组件.png

这样一个树形组件就完成了,然后因为业务需要把hasImg这个值通过$emit传给父组件去做一些操作处理,并且在这里直接做了转化,等于1时转为true,否则是false。但是这样在点击子节点其实是存在问题的,我们可以把值打印出来看下

vue.png 树形菜单.png

比如现在我点击了第四级节点,也就是title为1-1-1-1的这个节点,那么点击会向上级冒泡,可以看到实际这个点击方法触发了4次!而只有第一次的hasImg===1转化为true是正确的,第二次打印出来时hasImg的值已经变为了ture,这时hasImg===1转化为出来就变成了falsefalse继续再向上传之后转化出来肯定也都是false……这样在父组件实际接收到hasImg的值是false,而期望得到的应该是true才对。

解决方法

既然事件会往上冒泡,那么就阻止事件冒泡不就可以了

vuejs.png OK,再点击打印出来看下

vue.png

额,还是老样子。这里我大概想了下,应该是因为在组件上都用了vue@绑定了监听事件,然后调用了$emit来向上层传递,而禁止冒泡只是对原生事件起作用,并没有阻止vue事件的传递。既然这样那就不用@在组件上绑定事件,改用props来传递点击函数来试试

vue中递归生成树形节点组件.png

再点击打印出来看下

vue树形菜单.png

OK,这样就正确了,只触发了一次,hasImg===1转化后传递给父组件hasImg的值就是true了!

总结

因为自己平时还是用React为主的,在React中就没有这样的问题,因为React可以在当前组件通过调用函数生成返回树形组件,点击子节点可以直接调用到当前组件的方法,不存在父子组件传参的情况,所以也算是在vue的一次经验积累吧。当然在vue中可以用EventBus事件总线解决这个问题,或者也可以用JSX来解决这个问题,只是还没试过,如果有其他更好的解决方法,也欢迎留言交流哈~