fix v-on .once on multiple elements (fix #4655)

This commit is contained in:
Evan You 2017-01-13 12:14:23 -05:00
parent 1a1952ba81
commit ee6ad6af0e
2 changed files with 38 additions and 4 deletions

View File

@ -4,11 +4,17 @@ import { updateListeners } from 'core/vdom/helpers/index'
let target: HTMLElement
function add (event: string, handler: Function, once: boolean, capture: boolean) {
function add (
event: string,
handler: Function,
once: boolean,
capture: boolean
) {
if (once) {
const oldHandler = handler
const _target = target // save current target element in closure
handler = function (ev) {
remove(event, handler, capture)
remove(event, handler, capture, _target)
arguments.length === 1
? oldHandler(ev)
: oldHandler.apply(null, arguments)
@ -17,8 +23,13 @@ function add (event: string, handler: Function, once: boolean, capture: boolean)
target.addEventListener(event, handler, capture)
}
function remove (event: string, handler: Function, capture: boolean) {
target.removeEventListener(event, handler, capture)
function remove (
event: string,
handler: Function,
capture: boolean,
_target?: HTMLElement
) {
(_target || target).removeEventListener(event, handler, capture)
}
function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {

View File

@ -130,6 +130,29 @@ describe('Directive v-on', () => {
expect(spy.calls.count()).toBe(1) // should no longer trigger
})
// #4655
it('should handle .once on multiple elements properly', () => {
vm = new Vue({
el,
template: `
<div>
<button ref="one" @click.once="foo">one</button>
<button ref="two" @click.once="foo">two</button>
</div>
`,
methods: { foo: spy }
})
triggerEvent(vm.$refs.one, 'click')
expect(spy.calls.count()).toBe(1)
triggerEvent(vm.$refs.one, 'click')
expect(spy.calls.count()).toBe(1)
triggerEvent(vm.$refs.two, 'click')
expect(spy.calls.count()).toBe(2)
triggerEvent(vm.$refs.one, 'click')
triggerEvent(vm.$refs.two, 'click')
expect(spy.calls.count()).toBe(2)
})
it('should support capture and once', () => {
const callOrder = []
vm = new Vue({