fix $refs updateing (#3217)

ref: #3204
This commit is contained in:
kazuya kawaguchi 2016-07-06 00:08:13 +09:00 committed by Evan You
parent bbe09dfe75
commit c17e3876bf
5 changed files with 122 additions and 22 deletions

View File

@ -665,8 +665,8 @@ function makeTerminalNodeLinkFn (el, dirName, value, options, def, rawName, arg,
modifiers: modifiers,
def: def
}
// check ref for v-for and router-view
if (dirName === 'for' || dirName === 'router-view') {
// check ref for v-for, v-if and router-view
if (dirName === 'for' || dirName === 'if' || dirName === 'router-view') {
descriptor.ref = findRef(el)
}
var fn = function terminalNodeLinkFn (vm, el, host, scope, frag) {

View File

@ -16,7 +16,8 @@ import {
def,
cancellable,
isArray,
isPlainObject
isPlainObject,
findVmFromFrag
} from '../../util/index'
let uid = 0
@ -602,24 +603,6 @@ function findPrevFrag (frag, anchor, id) {
return frag
}
/**
* Find a vm from a fragment.
*
* @param {Fragment} frag
* @return {Vue|undefined}
*/
function findVmFromFrag (frag) {
let node = frag.node
// handle multi-node frag
if (frag.end) {
while (!node.__vue__ && node !== frag.end && node.nextSibling) {
node = node.nextSibling
}
}
return node.__vue__
}
/**
* Create a range array from given number.
*

View File

@ -5,7 +5,8 @@ import {
remove,
replace,
createAnchor,
warn
warn,
findVmFromFrag
} from '../../util/index'
export default {
@ -40,8 +41,10 @@ export default {
if (value) {
if (!this.frag) {
this.insert()
this.updateRef(value)
}
} else {
this.updateRef(value)
this.remove()
}
},
@ -76,6 +79,29 @@ export default {
}
},
updateRef (value) {
var ref = this.descriptor.ref
if (!ref) return
var hash = (this.vm || this._scope).$refs
var refs = hash[ref]
var key = this._frag.scope.$key
if (!refs) return
if (value) {
if (Array.isArray(refs)) {
refs.push(findVmFromFrag(this._frag))
} else {
refs[key] = findVmFromFrag(this._frag)
}
} else {
if (Array.isArray(refs)) {
refs.$remove(findVmFromFrag(this._frag))
} else {
refs[key] = null
delete refs[key]
}
}
},
unbind () {
if (this.frag) {
this.frag.destroy()

View File

@ -449,3 +449,21 @@ export function getOuterHTML (el) {
return container.innerHTML
}
}
/**
* Find a vm from a fragment.
*
* @param {Fragment} frag
* @return {Vue|undefined}
*/
export function findVmFromFrag (frag) {
let node = frag.node
// handle multi-node frag
if (frag.end) {
while (!node.__vue__ && node !== frag.end && node.nextSibling) {
node = node.nextSibling
}
}
return node.__vue__
}

View File

@ -432,4 +432,77 @@ describe('v-if', function () {
done()
})
})
// GitHub issue #3204
it('update array refs', function (done) {
var vm = new Vue({
el: el,
template: '<foo v-if="!activeItem || $index === activeItem" v-ref:foo :index="$index" v-for="item in items"></foo>',
data: {
items: [0, 1, 2],
activeItem: null
},
components: {
foo: {
props: ['index'],
template: '<div>I am foo ({{ index }})<div>'
}
}
})
vm.$refs.foo.forEach(function (ref, index) {
expect(ref.$el.textContent).toBe('I am foo (' + index + ')')
expect(ref.index).toBe(index)
})
vm.activeItem = 1 // select active item
nextTick(function () {
expect(vm.$refs.foo.length).toBe(1)
expect(vm.$refs.foo[0].index).toBe(1)
vm.activeItem = null // enable all elements
nextTick(function () {
expect(vm.$refs.foo.length).toBe(3)
done()
})
})
})
it('update object refs', function (done) {
var vm = new Vue({
el: el,
template: '<foo v-if="!activeKey || $key === activeKey" v-ref:foo :key="$key" v-for="item in items"></foo>',
data: {
items: {
a: 1,
b: 2,
c: 3
},
activeKey: null
},
components: {
foo: {
props: ['key'],
template: '<div>I am foo ({{ key }})<div>'
}
}
})
Object.keys(vm.$refs.foo).forEach(function (key) {
var ref = vm.$refs.foo[key]
expect(ref.$el.textContent).toBe('I am foo (' + key + ')')
expect(ref.key).toBe(key)
})
vm.activeKey = 'b' // select active item
nextTick(function () {
expect(Object.keys(vm.$refs.foo).length).toBe(1)
expect(vm.$refs.foo['b'].key).toBe('b')
vm.activeKey = null // enable all elements
nextTick(function () {
expect(Object.keys(vm.$refs.foo).length).toBe(3)
Object.keys(vm.$refs.foo).forEach(function (key) {
var ref = vm.$refs.foo[key]
expect(ref.$el.textContent).toBe('I am foo (' + key + ')')
expect(ref.key).toBe(key)
})
done()
})
})
})
})