8000 fix v-ref for dynamic components with keep-alive (fix #1695) · zhangking/vue@fbfcfcc · GitHub
[go: up one dir, main page]

Skip to content

Commit fbfcfcc

Browse files
committed
fix v-ref for dynamic components with keep-alive (fix vuejs#1695)
1 parent d2821b0 commit fbfcfcc

File tree

5 files changed

+54
-13
lines changed

5 files changed

+54
-13
lines changed

src/directives/internal/component.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ module.exports = {
132132
self.transition(newComponent, cb)
133133
})
134134
} else {
135+
// update ref for kept-alive component
136+
if (cached) {
137+
newComponent._updateRef()
138+
}
135139
this.transition(newComponent, cb)
136140
}
137141
},
@@ -241,6 +245,10 @@ module.exports = {
241245
}
242246
var child = this.childVM
243247
if (!child || this.keepAlive) {
248+
if (child) {
249+
// remove ref
250+
child._updateRef(true)
251+
}
244252
return
245253
}
246254
// the sole purpose of `deferCleanup` is so that we can

src/instance/init.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,16 @@ exports._init = function (options) {
7979
this.$parent.$children.push(this)
8080
}
8181

82-
// set ref
83-
if (options._ref) {
84-
(this._scope || this._context).$refs[options._ref] = this
85-
}
86-
8782
// merge options.
8883
options = this.$options = mergeOptions(
8984
this.constructor.options,
9085
options,
9186
this
9287
)
9388

89+
// set ref
90+
this._updateRef()
91+
9492
// initialize data as empty object.
9593
// it will be filled up in _initScope().
9694
this._data = {}

src/instance/lifecycle.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@ var _ = require('../util')
22
var Directive = require('../directive')
33
var compiler = require('../compiler')
44

5+
/**
6+
* Update v-ref for component.
7+
*
8+
* @param {Boolean} remove
9+
*/
10+
11+
exports._updateRef = function (remove) {
12+
var ref = this.$options._ref
13+
if (ref) {
14+
var refs = (this._scope || this._context).$refs
15+
if (remove) {
16+
if (refs[ref] === this) {
17+
refs[ref] = null
18+
}
19+
} else {
20+
refs[ref] = this
21+
}
22+
}
23+
}
24+
525
/**
626
* Transclude, compile and link element.
727
*
@@ -136,14 +156,8 @@ exports._destroy = function (remove, deferCleanup) {
136156
var parent = this.$parent
137157
if (parent && !parent._isBeingDestroyed) {
138158
parent.$children.$remove(this)
139-
// unregister ref
140-
var ref = this.$options._ref
141-
if (ref) {
142-
var scope = this._scope || this._context
143-
if (scope.$refs[ref] === this) {
144-
scope.$refs[ref] = null
145-
}
146-
}
159+
// unregister ref (remove: true)
160+
this._updateRef(true)
147161
}
148162
// destroy all children.
149163
i = this.$children.length

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,25 @@ if (_.inBrowser) {
5353
})
5454
})
5555

56+
it('with dynamic component + keep-alive', function (done) {
57+
var vm = new Vue({
58+
el: el,
59+
components: components,
60+
data: { test: 'test' },
61+
template: '<component :is="test" v-ref:test keep-alive></component>'
62+
})
63+
expect(vm.$refs.test.$options.id).toBe('test')
64+
vm.test = 'test2'
65+
_.nextTick(function () {
66+
expect(vm.$refs.test.$options.id).toBe('test2')
67+
vm.test = ''
68+
_.nextTick(function () {
69+
expect(vm.$refs.test).toBe(null)
70+
done()
71+
})
72+
})
73+
})
74+
5675
it('should be reactive when bound by dynamic component and hoisted', function (done) {
5776
var vm = new Vue({
5877
el: el,

test/unit/specs/instance/init_spec.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ describe('Instance Init', function () {
66
constructor: {
77
options: { a: 1, b: 2 }
88
},
9+
_updateRef: jasmine.createSpy(),
910
_initEvents: jasmine.createSpy(),
1011
_callHook: jasmine.createSpy(),
1112
_initState: jasmine.createSpy(),
@@ -38,6 +39,7 @@ describe('Instance Init', function () {
3839
it('should call other init methods', function () {
3940
expect(stub._initEvents).toHaveBeenCalled()
4041
expect(stub._initState).toHaveBeenCalled()
42+
expect(stub._updateRef).toHaveBeenCalled()
4143
})
4244

4345
it('should call created hook', function () {

0 commit comments

Comments
 (0)
0