解决vue watch中removeEventListener()不生效的问题

解决vue watch中removeEventListener()不生效的问题

最近在做vue项目,遇到了一个事件绑定的小问题,当我watch某一个data值的变化时,需要对某一个节点绑定事件(先解绑再绑定,防止重复绑定),可以来看下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
data() {
return {
quickSelect: '',
inputValue: ''
}
},
watch: {
inputValue: {
handler() {
const datePickerPanel = document.querySelector('.date-picker__panel')
const _this = this // 闭包取不到vue实例,所以要在这里重新定义
const clearQuickSelect = function () {
console.log(1111)
_this.quickSelect = ''
}
// 防止重复监听,先移除之前的
datePickerPanel.removeEventListener('click', clearQuickSelect, false)
datePickerPanel.addEventListener('click', clearQuickSelect, false)
// 触发panel刷新函数
this.refreshPanel()
}
}
},
methods: {
refreshPanel() {
...
this.quickSelect = 'xxx'
...
}
}
...

我在watch中去声明了一个clearQuickSelect函数,重置quickSelect这个属性,乍一看add和remove的参数完全一致,在实际操作中发现remove并没有生效,原因是啥呢,我还傻乎乎的用箭头函数试了一下,依然还是无法remove。

其实主要问题在于,每次触发watch,都会生成一个新的clearQuickSelect函数,即便名字一样,它所存放的地址也发生了变化,实际上每次remove的clearQuickSelect都是一个新的函数,简单来说,就是生成了clearQuickSelect1() clearQuickSelect2() clearQuickSelect3(),导致解绑不到之前定义的函数。

一个解决办法就是将clearQuickSelect放在methods里,这样一解决了上面的问题,二也不需要考虑闭包取不到正确的this的问题。

说道这里不如来回顾一下从原生到jquery再到目前主流框架的事件绑定方法吧

框架 事件
原生js addEventListener(event, function, useCapture), removeEventListener(event, function, useCapture)
jquery $(domSelector).on(event, childSelector, data, function), $(domSelector).off(‘click’)
vue 在dom上绑定@click=”func()”或使用原生
react 在dom上绑定onClick=”func()”或使用原生

PS: 原生事件中useCapture为true则表示在捕获阶段触发,否则为冒泡。默认为事件冒泡。

最近面试也被问到了一个问题,如何使用原生事件实现jquery的on,简单想了一种写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="father">
<div class="child"></div>
<div class="child"></div>
</div>
<script>
// jquery的写法
$('#father').on('click', '.child', function () {console.log(111111)} )
// 用原生实现
const father = document.getElementById('father')
father.addEventListener('click', function(e) {
if (e && e.target.className = 'child') {
console.log(222222)
}
})
</script>
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×