JS事件绑定中的坑
模态框:早就发现但没有重视的问题
之前写模态框时就注意到了一些问题,例如有些时候点击按钮会弹出多个模态框,这并不是我想要的结果。
我不清楚这是为什么,但是这种情况很好解决,我直接在模态框组件的构造函数里加一个判断,就解决了这个问题:
1 | if(_.$('.m-modal')) return |
模态框又出现了其它问题
事件还原:
模态框的“确定”按钮会调用一个自身的事件,注销掉这个窗体:
1 | hide: function() { |
某一次我调用完模态框,点击其中的“确定”按钮,窗体正常关闭了。但控制台报了一个错:Failed to execute 'removeChild' on 'Node',也就是说,它没有找到窗体节点,在控制台console了一下,果然是这样的。
但是窗体毕竟是正常关闭了,出现这个bug只能说明这个接口被多次调用了。
解决问题
好吧,延续上个问题的解决思路:
1 | hide: function() { |
这个时候其实就应该考虑到了,这个组件已经实现了很多接口了,难道要一直用这种笨办法吗?
但是毕竟还有其它的工作等着完成(其实是其它bug等着修复),就先把这个问题搁置了。
其它组件中也出现了bug
很不幸,紧接着就发现其它组件中出现了同一个方法点击时被执行了两次,如图:
看来这个问题不彻底解决是不行了。
一开始我怀疑是元素冒泡导致的问题,然后在事件调用时添加了event.stopPropagation()来阻止冒泡,但发现没什么卵用。
在网上查资料,发现有很多类似的案例,原来是因为事件被重复多次绑定到了这个元素上:
如图,在event listenners选项卡中,可以查看绑定的全部事件,在这里我的m-works组件被绑定了两个完全一样的事件。
解决办法就是用JQuery的once去接口绑定事件或者off接口及时解绑。
但我并不能因为一个bug去调用一个如此庞大的库。随后,我又在stackoverflow里找到了一个原生的解决办法,思路是把这个事件方法拿出来,写在一个新的函数中,然后绑定到这个新的函数
1 | var newHandle = function(event) { handle(event, myArgument); }; |
但不知为什么,它在我这里仍然是无效的。
无奈之下问群里的同学,有个同学给出了一个这样的接口:event.stopImmediatePropagation,
它的作用是阻止调用相同事件的其他侦听器。
万万没想到,竟有这样的神器?!果然,在我把它加在事件函数内的首行后,虽然它仍旧绑定了两个相同的方法,但实际上只会被调用一次,问题就这样解决了。
总结及思考
- 遇到bug最好还是追根刨底,斩草不除根,春风吹又生啊
- 多记一些API是很有用的,哪怕只是过一遍,也比杆瞎强多了

