Skip to content

Commit 2eee405

Browse files
committed
component wait-for & transition-mode
1 parent 7d3b87f commit 2eee405

File tree

6 files changed

+173
-30
lines changed

6 files changed

+173
-30
lines changed

src/api/lifecycle.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ exports.$destroy = function (remove, cb) {
103103
})
104104
} else {
105105
cleanup(self)
106-
if (cb) cb()
107106
}
108107
}
109108

src/directive.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,21 @@ p._checkStatement = function () {
153153
}
154154
}
155155

156+
/**
157+
* Check for an attribute directive param, e.g. lazy
158+
*
159+
* @param {String} name
160+
* @return {String}
161+
*/
162+
163+
p._checkParam = function (name) {
164+
var param = this.el.getAttribute(name)
165+
if (param !== null) {
166+
this.el.removeAttribute(name)
167+
}
168+
return param
169+
}
170+
156171
/**
157172
* Teardown the watcher and call unbind.
158173
*/

src/directives/component.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ module.exports = {
3535
this.childVM = this.build()
3636
this.childVM.$before(this.ref)
3737
} else {
38-
this.readyEvent = this.el.getAttribute('ready-event')
39-
this.transMode = this.el.getAttribute('transition-mode')
38+
// check dynamic component params
39+
this.readyEvent = this._checkParam('wait-for')
40+
this.transMode = this._checkParam('transition-mode')
4041
}
4142
} else {
4243
_.warn(
@@ -147,7 +148,7 @@ module.exports = {
147148
var child = this.build()
148149
var self = this
149150
if (this.readyEvent) {
150-
child.$on(this.readyEvent, function () {
151+
child.$once(this.readyEvent, function () {
151152
self.swapTo(child)
152153
})
153154
} else {
@@ -169,18 +170,20 @@ module.exports = {
169170
case 'in-out':
170171
child.$before(self.ref, function () {
171172
self.unbuild(true)
173+
self.childVM = child
172174
})
173175
break
174176
case 'out-in':
175177
self.unbuild(true, function () {
176178
child.$before(self.ref)
179+
self.childVM = child
177180
})
178181
break
179182
default:
180183
self.unbuild(true)
181184
child.$before(self.ref)
185+
self.childVM = child
182186
}
183-
self.childVM = child
184187
},
185188

186189
/**
@@ -201,6 +204,7 @@ module.exports = {
201204
}
202205
child.$destroy()
203206
}
207+
this.cache = null
204208
}
205209
}
206210

src/directives/model/select.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ module.exports = {
77
var self = this
88
var el = this.el
99
// check options param
10-
var optionsParam = el.getAttribute('options')
10+
var optionsParam = this._checkParam('options')
1111
if (optionsParam) {
12-
el.removeAttribute('options')
1312
initOptions.call(this, optionsParam)
1413
}
1514
this.multiple = el.hasAttribute('multiple')

src/directives/repeat.js

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ module.exports = {
4040
// at v-repeat level
4141
this.checkIf()
4242
this.checkRef()
43-
this.checkTrackById()
4443
this.checkComponent()
44+
// check for trackby param
45+
this.idKey = this._checkParam('trackby')
4546
// cache for primitive value instances
4647
this.cache = Object.create(null)
4748
},
@@ -74,19 +75,6 @@ module.exports = {
7475
: null
7576
},
7677

77-
/**
78-
* Check for a track-by ID, which allows us to identify
79-
* a piece of data and its associated instance by its
80-
* unique id.
81-
*/
82-
83-
checkTrackById: function () {
84-
this.idKey = this.el.getAttribute('trackby')
85-
if (this.idKey !== null) {
86-
this.el.removeAttribute('trackby')
87-
}
88-
},
89-
9078
/**
9179
* Check the component constructor to use for repeated
9280
* instances. If static we resolve it now, otherwise it

test/unit/specs/directives/component_spec.js

Lines changed: 147 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,11 @@ if (_.inBrowser) {
8686
vm.view = 'b'
8787
_.nextTick(function () {
8888
expect(el.innerHTML).toBe('<div view="b">BBB</div><!--v-component-->')
89-
done()
89+
vm.view = ''
90+
_.nextTick(function () {
91+
expect(el.innerHTML).toBe('<!--v-component-->')
92+
done()
93+
})
9094
})
9195
})
9296

@@ -195,19 +199,153 @@ if (_.inBrowser) {
195199
})
196200
})
197201

198-
it('teardown', function () {
202+
it('wait-for', function (done) {
203+
var vm = new Vue({
204+
el: el,
205+
data: {
206+
view: 'a'
207+
},
208+
template: '<div v-component="{{view}}" wait-for="ok"></div>',
209+
components: {
210+
a: {
211+
template: 'AAA'
212+
},
213+
b: {
214+
template: 'BBB'
215+
}
216+
}
217+
})
218+
vm._children[0].$emit('ok')
219+
vm.view = 'b'
220+
_.nextTick(function () {
221+
expect(el.textContent).toBe('AAA')
222+
vm._children[1].$emit('ok')
223+
expect(el.textContent).toBe('BBB')
224+
done()
225+
})
226+
})
227+
228+
it('transition-mode: in-out', function (done) {
229+
var spy1 = jasmine.createSpy('enter')
230+
var spy2 = jasmine.createSpy('leave')
231+
var next
232+
// === IMPORTANT ===
233+
// PhantomJS always returns false when calling
234+
// Element.contains() on a comment node. This causes
235+
// transitions to be skipped. Monkey patching here
236+
// isn't ideal but does the job...
237+
var inDoc = _.inDoc
238+
_.inDoc = function () {
239+
return true
240+
}
199241
var vm = new Vue({
200242
el: el,
201-
data: { ok: true },
202-
template: '<div v-component="test" v-if="ok"></div>',
243+
data: {
244+
view: 'a'
245+
},
246+
template: '<div v-component="{{view}}" v-transition="test" transition-mode="in-out"></div>',
203247
components: {
204-
test: {}
248+
a: { template: 'AAA' },
249+
b: { template: 'BBB' }
250+
},
251+
transitions: {
252+
test: {
253+
enter: function (el, done) {
254+
spy1()
255+
next = done
256+
},
257+
leave: function (el, done) {
258+
spy2()
259+
done()
260+
}
261+
}
205262
}
206263
})
207-
var child = vm._children[0]
208-
vm._directives[0].unbind()
209-
expect(vm._children.length).toBe(0)
210-
expect(child._isDestroyed).toBe(true)
264+
expect(el.textContent).toBe('AAA')
265+
vm.view = 'b'
266+
_.nextTick(function () {
267+
expect(spy1).toHaveBeenCalled()
268+
expect(spy2).not.toHaveBeenCalled()
269+
expect(el.textContent).toBe('AAABBB')
270+
next()
271+
expect(spy2).toHaveBeenCalled()
272+
expect(el.textContent).toBe('BBB')
273+
// clean up
274+
_.inDoc = inDoc
275+
done()
276+
})
277+
})
278+
279+
it('transition-mode: out-in', function (done) {
280+
var spy1 = jasmine.createSpy('enter')
281+
var spy2 = jasmine.createSpy('leave')
282+
var next
283+
var inDoc = _.inDoc
284+
_.inDoc = function () {
285+
return true
286+
}
287+
var vm = new Vue({
288+
el: el,
289+
data: {
290+
view: 'a'
291+
},
292+
template: '<div v-component="{{view}}" v-transition="test" transition-mode="out-in"></div>',
293+
components: {
294+
a: { template: 'AAA' },
295+
b: { template: 'BBB' }
296+
},
297+
transitions: {
298+
test: {
299+
enter: function (el, done) {
300+
spy2()
301+
done()
302+
},
303+
leave: function (el, done) {
304+
spy1()
305+
next = done
306+
}
307+
}
308+
}
309+
})
310+
expect(el.textContent).toBe('AAA')
311+
vm.view = 'b'
312+
_.nextTick(function () {
313+
expect(spy1).toHaveBeenCalled()
314+
expect(spy2).not.toHaveBeenCalled()
315+
expect(el.textContent).toBe('AAA')
316+
next()
317+
expect(spy2).toHaveBeenCalled()
318+
expect(el.textContent).toBe('BBB')
319+
// clean up
320+
_.inDoc = inDoc
321+
done()
322+
})
323+
})
324+
325+
it('teardown', function (done) {
326+
var vm = new Vue({
327+
el: el,
328+
template: '<div v-component="{{view}}" keep-alive></div>',
329+
data: {
330+
view: 'test'
331+
},
332+
components: {
333+
test: {},
334+
test2: {}
335+
}
336+
})
337+
vm.view = 'test2'
338+
_.nextTick(function () {
339+
expect(vm._children.length).toBe(2)
340+
var child = vm._children[0]
341+
var child2 = vm._children[1]
342+
vm._directives[0].unbind()
343+
expect(vm._directives[0].cache).toBeNull()
344+
expect(vm._children.length).toBe(0)
345+
expect(child._isDestroyed).toBe(true)
346+
expect(child2._isDestroyed).toBe(true)
347+
done()
348+
})
211349
})
212350

213351
it('already mounted warn', function () {

0 commit comments

Comments
 (0)