Browse Source

unbind v-show if no longer present during patch (fix #4484)

dev
Evan You 8 years ago
parent
commit
a977642fac
  1. 7
      src/core/vdom/modules/directives.js
  2. 13
      src/platforms/web/runtime/directives/show.js
  3. 17
      test/unit/features/directives/show.spec.js

7
src/core/vdom/modules/directives.js

@ -20,6 +20,7 @@ function updateDirectives (oldVnode: VNodeWithData, vnode: VNodeWithData) {
function _update (oldVnode, vnode) {
const isCreate = oldVnode === emptyNode
const isDestroy = vnode === emptyNode
const oldDirs = normalizeDirectives(oldVnode.data.directives, oldVnode.context)
const newDirs = normalizeDirectives(vnode.data.directives, vnode.context)
@ -71,7 +72,7 @@ function _update (oldVnode, vnode) {
for (key in oldDirs) {
if (!newDirs[key]) {
// no longer present, unbind
callHook(oldDirs[key], 'unbind', oldVnode)
callHook(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy)
}
}
}
@ -103,9 +104,9 @@ function getRawDirName (dir: VNodeDirective): string {
return dir.rawName || `${dir.name}.${Object.keys(dir.modifiers || {}).join('.')}`
}
function callHook (dir, hook, vnode, oldVnode) {
function callHook (dir, hook, vnode, oldVnode, isDestroy) {
const fn = dir.def && dir.def[hook]
if (fn) {
fn(vnode.elm, dir, vnode, oldVnode)
fn(vnode.elm, dir, vnode, oldVnode, isDestroy)
}
}

13
src/platforms/web/runtime/directives/show.js

@ -25,6 +25,7 @@ export default {
el.style.display = value ? originalDisplay : 'none'
}
},
update (el: any, { value, oldValue }: VNodeDirective, vnode: VNodeWithData) {
/* istanbul ignore if */
if (value === oldValue) return
@ -44,5 +45,17 @@ export default {
} else {
el.style.display = value ? el.__vOriginalDisplay : 'none'
}
},
unbind (
el: any,
binding: VNodeDirective,
vnode: VNodeWithData,
oldVnode: VNodeWithData,
isDestroy: boolean
) {
if (!isDestroy) {
el.style.display = el.__vOriginalDisplay
}
}
}

17
test/unit/features/directives/show.spec.js

@ -64,4 +64,21 @@ describe('Directive v-show', () => {
expect(vm.$el.firstChild.style.display).toBe('block')
}).then(done)
})
it('should support unbind when reused', done => {
const vm = new Vue({
template:
'<div v-if="tester"><span v-show="false"></span></div>' +
'<div v-else><span @click="tester=!tester">show</span></div>',
data: { tester: true }
}).$mount()
expect(vm.$el.firstChild.style.display).toBe('none')
vm.tester = false
waitForUpdate(() => {
expect(vm.$el.firstChild.style.display).toBe('')
vm.tester = true
}).then(() => {
expect(vm.$el.firstChild.style.display).toBe('none')
}).then(done)
})
})

Loading…
Cancel
Save