Vue.js 클로저(Closure) 이벤트 핸들러 무반응 문제 해결
Vue.js
에서 아래와 같이 이벤트 핸들러로 클로저 형태의 핸들러 함수를 넘겨주게 되면 의도된 대로 동작하지 않고, 그렇다고 특별한 에러도 없이 아무런 반응이 없어 문제가 있는것을 확인 할 수 있다.
JavaScript
Vue.component('BaseCheckbox', {
name: 'BaseCheckBox',
template:
`
<button type="button">
<slot></slot>
</button>
`
});
new Vue({
el: "#app",
methods: {
closureHandler: function(msg) {
return evt => { alert(msg) }
}
}
})
HTML
<div id="app">
<label>
<!-- It will not work -->
<base-checkbox v-on:click.native="closureHandler('foobar')">
Click me
</base-checkbox>
</label>
</div>
이에 대한 해결 방법을 연구하다 크게 두가지 해결법을 알아내어 기록해본다.
props
로 callback
넘겨주기
JavaScript
Vue.component('BaseCheckbox', {
name: 'BaseCheckBox',
template:
`
<button type="button" v-on:click="onClick">
<slot></slot>
</button>
`,
props: ['callback'],
methods: {
onClick: function(evt) {
this.callback(evt);
}
}
});
new Vue({
el: "#app",
methods: {
closureHandler: function(msg) {
return evt => { alert(msg) }
}
}
})
HTML
<div id="app">
<label>
<!-- Make it work -->
<base-checkbox v-bind:callback="closureHandler('foobar')">
Click me
</base-checkbox>
</label>
</div>
자식이 되는 컴포넌트에서 이벤트 바인딩을 하여 props
로 받은 callback
함수를 호출하도록 하는 해결방법이다.
object handler
사용
JavaScript
Vue.component('BaseCheckbox', {
name: 'BaseCheckBox',
template:
`
<button type="button" v-on:click="onClick">
<slot></slot>
</button>
`,
methods: {
onClick: function(evt) {
this.$emit('press', evt);
}
}
});
new Vue({
el: "#app",
methods: {
closureHandler: function(msg) {
return evt => { alert(msg) }
}
}
})
HTML
<div id="app">
<label>
<!-- Make it work 2 -->
<base-checkbox v-on="{ press: closureHandler('foobar') }">
Click me
</base-checkbox>
</label>
</div>
마찬가지로 자식 컴포넌트에서 이벤트 바인딩을 하고, this.$emit(...)
을 이용하여 부모에서 특정 이벤트로 바인딩을 할 수 있도록 전달해주는 방법이다. click
은 원래 native event
로 존재하기 때문에 press
라는 커스텀 이벤트를 발생시키도록 하였다.