Skip to content

Commit 3caa52e

Browse files
committed
implement activate hook
1 parent 17d8e24 commit 3caa52e

File tree

2 files changed

+135
-10
lines changed

2 files changed

+135
-10
lines changed

src/directives/component.js

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,28 @@ module.exports = {
8888
var anchor = this.el
8989
var options
9090
var waitFor = this.waitForEvent
91+
var activateHook = this.Component.options.activate
9192
if (waitFor) {
9293
options = {
9394
created: function () {
94-
this.$once(waitFor, function () {
95-
this.$before(anchor)
96-
_.remove(anchor)
97-
})
95+
this.$once(waitFor, insert)
9896
}
9997
}
10098
}
10199
var child = this.build(options)
102100
this.setCurrent(child)
103101
if (!this.waitForEvent) {
104-
child.$before(anchor)
102+
if (activateHook) {
103+
activateHook.call(child, insert)
104+
} else {
105+
child.$before(anchor)
106+
_.remove(anchor)
107+
}
108+
}
109+
function insert () {
110+
// TODO: no need to fallback to this in 1.0.0
111+
// once wait-for is removed
112+
(child || this).$before(anchor)
105113
_.remove(anchor)
106114
}
107115
},
@@ -141,22 +149,30 @@ module.exports = {
141149
var options
142150
var self = this
143151
var waitFor = this.waitForEvent
152+
var activateHook = this.Component.options.activate
144153
if (waitFor) {
145154
options = {
146155
created: function () {
147-
this.$once(waitFor, function () {
148-
self.waitingFor = null
149-
self.transition(this, cb)
150-
})
156+
this.$once(waitFor, insert)
151157
}
152158
}
153159
}
154160
var cached = this.getCached()
155161
var newComponent = this.build(options)
156-
if (!waitFor || cached) {
162+
if ((!waitFor && !activateHook) || cached) {
157163
this.transition(newComponent, cb)
158164
} else {
159165
this.waitingFor = newComponent
166+
if (activateHook) {
167+
activateHook.call(newComponent, insert)
168+
}
169+
}
170+
171+
function insert () {
172+
self.waitingFor = null
173+
// TODO: no need to fallback to this in 1.0.0
174+
// once wait-for is removed
175+
self.transition((newComponent || this), cb)
160176
}
161177
}, this))
162178
}

test/unit/specs/directives/component_spec.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,26 @@ if (_.inBrowser) {
314314
expect(el.textContent).toBe('AAA')
315315
})
316316

317+
it('activate hook for static component', function (done) {
318+
new Vue({
319+
el: el,
320+
template: '<view-a></view-a>',
321+
components: {
322+
'view-a': {
323+
template: 'AAA',
324+
activate: function (ready) {
325+
setTimeout(function () {
326+
expect(el.textContent).toBe('')
327+
ready()
328+
expect(el.textContent).toBe('AAA')
329+
done()
330+
}, 0)
331+
}
332+
}
333+
}
334+
})
335+
})
336+
317337
it('sync wait-for inside compiled hook', function () {
318338
new Vue({
319339
el: el,
@@ -371,6 +391,55 @@ if (_.inBrowser) {
371391
})
372392
})
373393

394+
it('activate hook for dynamic components', function (done) {
395+
var next
396+
var vm = new Vue({
397+
el: el,
398+
data: {
399+
view: 'view-a'
400+
},
401+
template: '<component bind-is="view"></component>',
402+
components: {
403+
'view-a': {
404+
template: 'AAA',
405+
activate: function (ready) {
406+
next = ready
407+
}
408+
},
409+
'view-b': {
410+
template: 'BBB',
411+
activate: function (ready) {
412+
next = ready
413+
}
414+
}
415+
}
416+
})
417+
expect(next).toBeTruthy()
418+
expect(el.textContent).toBe('')
419+
next()
420+
expect(el.textContent).toBe('AAA')
421+
vm.view = 'view-b'
422+
_.nextTick(function () {
423+
expect(el.textContent).toBe('AAA')
424+
// old vm is already removed, this is the new vm
425+
expect(vm.$children.length).toBe(1)
426+
next()
427+
expect(el.textContent).toBe('BBB')
428+
// ensure switching before ready event correctly
429+
// cleans up the component being waited on.
430+
// see #1152
431+
vm.view = 'view-a'
432+
_.nextTick(function () {
433+
vm.view = 'view-b'
434+
_.nextTick(function () {
435+
expect(vm.$children.length).toBe(1)
436+
expect(vm.$children[0].$el.textContent).toBe('BBB')
437+
done()
438+
})
439+
})
440+
})
441+
})
442+
374443
// #1150
375444
it('wait-for + keep-alive', function (done) {
376445
var vm = new Vue({
@@ -405,6 +474,46 @@ if (_.inBrowser) {
405474
})
406475
})
407476

477+
it('activate hook + keep-alive', function (done) {
478+
var next
479+
var vm = new Vue({
480+
el: el,
481+
data: {
482+
view: 'view-a'
483+
},
484+
template: '<component bind-is="view" keep-alive></component>',
485+
components: {
486+
'view-a': {
487+
template: 'AAA',
488+
activate: function (ready) {
489+
next = ready
490+
}
491+
},
492+
'view-b': {
493+
template: 'BBB',
494+
activate: function (ready) {
495+
next = ready
496+
}
497+
}
498+
}
499+
})
500+
next()
501+
expect(el.textContent).toBe('AAA')
502+
vm.view = 'view-b'
503+
_.nextTick(function () {
504+
expect(vm.$children.length).toBe(2)
505+
next()
506+
expect(el.textContent).toBe('BBB')
507+
vm.view = 'view-a'
508+
_.nextTick(function () {
509+
// should switch without the need to emit
510+
// because of keep-alive
511+
expect(el.textContent).toBe('AAA')
512+
done()
513+
})
514+
})
515+
})
516+
408517
it('transition-mode: in-out', function (done) {
409518
var spy1 = jasmine.createSpy('enter')
410519
var spy2 = jasmine.createSpy('leave')

0 commit comments

Comments
 (0)