Skip to content

Commit c17e387

Browse files
kazuponyyx990803
authored andcommitted
fix $refs updateing (vuejs#3217)
ref: vuejs#3204
1 parent bbe09df commit c17e387

File tree

5 files changed

+122
-22
lines changed

5 files changed

+122
-22
lines changed

src/compiler/compile.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,8 @@ function makeTerminalNodeLinkFn (el, dirName, value, options, def, rawName, arg,
665665
modifiers: modifiers,
666666
def: def
667667
}
668-
// check ref for v-for and router-view
669-
if (dirName === 'for' || dirName === 'router-view') {
668+
// check ref for v-for, v-if and router-view
669+
if (dirName === 'for' || dirName === 'if' || dirName === 'router-view') {
670670
descriptor.ref = findRef(el)
671671
}
672672
var fn = function terminalNodeLinkFn (vm, el, host, scope, frag) {

src/directives/public/for.js

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
def,
1717
cancellable,
1818
isArray,
19-
isPlainObject
19+
isPlainObject,
20+
findVmFromFrag
2021
} from '../../util/index'
2122

2223
let uid = 0
@@ -602,24 +603,6 @@ function findPrevFrag (frag, anchor, id) {
602603
return frag
603604
}
604605

605-
/**
606-
* Find a vm from a fragment.
607-
*
608-
* @param {Fragment} frag
609-
* @return {Vue|undefined}
610-
*/
611-
612-
function findVmFromFrag (frag) {
613-
let node = frag.node
614-
// handle multi-node frag
615-
if (frag.end) {
616-
while (!node.__vue__ && node !== frag.end && node.nextSibling) {
617-
node = node.nextSibling
618-
}
619-
}
620-
return node.__vue__
621-
}
622-
623606
/**
624607
* Create a range array from given number.
625608
*

src/directives/public/if.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
remove,
66
replace,
77
createAnchor,
8-
warn
8+
warn,
9+
findVmFromFrag
910
} from '../../util/index'
1011

1112
export default {
@@ -40,8 +41,10 @@ export default {
4041
if (value) {
4142
if (!this.frag) {
4243
this.insert()
44+
this.updateRef(value)
4345
}
4446
} else {
47+
this.updateRef(value)
4548
this.remove()
4649
}
4750
},
@@ -76,6 +79,29 @@ export default {
7679
}
7780
},
7881

82+
updateRef (value) {
83+
var ref = this.descriptor.ref
84+
if (!ref) return
85+
var hash = (this.vm || this._scope).$refs
86+
var refs = hash[ref]
87+
var key = this._frag.scope.$key
88+
if (!refs) return
89+
if (value) {
90+
if (Array.isArray(refs)) {
91+
refs.push(findVmFromFrag(this._frag))
92+
} else {
93+
refs[key] = findVmFromFrag(this._frag)
94+
}
95+
} else {
96+
if (Array.isArray(refs)) {
97+
refs.$remove(findVmFromFrag(this._frag))
98+
} else {
99+
refs[key] = null
100+
delete refs[key]
101+
}
102+
}
103+
},
104+
79105
unbind () {
80106
if (this.frag) {
81107
this.frag.destroy()

src/util/dom.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,3 +449,21 @@ export function getOuterHTML (el) {
449449
return container.innerHTML
450450
}
451451
}
452+
453+
/**
454+
* Find a vm from a fragment.
455+
*
456+
* @param {Fragment} frag
457+
* @return {Vue|undefined}
458+
*/
459+
460+
export function findVmFromFrag (frag) {
461+
let node = frag.node
462+
// handle multi-node frag
463+
if (frag.end) {
464+
while (!node.__vue__ && node !== frag.end && node.nextSibling) {
465+
node = node.nextSibling
466+
}
467+
}
468+
return node.__vue__
469+
}

test/unit/specs/directives/public/if_spec.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,4 +432,77 @@ describe('v-if', function () {
432432
done()
433433
})
434434
})
435+
436+
// GitHub issue #3204
437+
it('update array refs', function (done) {
438+
var vm = new Vue({
439+
el: el,
440+
template: '<foo v-if="!activeItem || $index === activeItem" v-ref:foo :index="$index" v-for="item in items"></foo>',
441+
data: {
442+
items: [0, 1, 2],
443+
activeItem: null
444+
},
445+
components: {
446+
foo: {
447+
props: ['index'],
448+
template: '<div>I am foo ({{ index }})<div>'
449+
}
450+
}
451+
})
452+
vm.$refs.foo.forEach(function (ref, index) {
453+
expect(ref.$el.textContent).toBe('I am foo (' + index + ')')
454+
expect(ref.index).toBe(index)
455+
})
456+
vm.activeItem = 1 // select active item
457+
nextTick(function () {
458+
expect(vm.$refs.foo.length).toBe(1)
459+
expect(vm.$refs.foo[0].index).toBe(1)
460+
vm.activeItem = null // enable all elements
461+
nextTick(function () {
462+
expect(vm.$refs.foo.length).toBe(3)
463+
done()
464+
})
465+
})
466+
})
467+
468+
it('update object refs', function (done) {
469+
var vm = new Vue({
470+
el: el,
471+
template: '<foo v-if="!activeKey || $key === activeKey" v-ref:foo :key="$key" v-for="item in items"></foo>',
472+
data: {
473+
items: {
474+
a: 1,
475+
b: 2,
476+
c: 3
477+
},
478+
activeKey: null
479+
},
480+
components: {
481+
foo: {
482+
props: ['key'],
483+
template: '<div>I am foo ({{ key }})<div>'
484+
}
485+
}
486+
})
487+
Object.keys(vm.$refs.foo).forEach(function (key) {
488+
var ref = vm.$refs.foo[key]
489+
expect(ref.$el.textContent).toBe('I am foo (' + key + ')')
490+
expect(ref.key).toBe(key)
491+
})
492+
vm.activeKey = 'b' // select active item
493+
nextTick(function () {
494+
expect(Object.keys(vm.$refs.foo).length).toBe(1)
495+
expect(vm.$refs.foo['b'].key).toBe('b')
496+
vm.activeKey = null // enable all elements
497+
nextTick(function () {
498+
expect(Object.keys(vm.$refs.foo).length).toBe(3)
499+
Object.keys(vm.$refs.foo).forEach(function (key) {
500+
var ref = vm.$refs.foo[key]
501+
expect(ref.$el.textContent).toBe('I am foo (' + key + ')')
502+
expect(ref.key).toBe(key)
503+
})
504+
done()
505+
})
506+
})
507+
})
435508
})

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy