Skip to content

Commit

Permalink
lifecycle hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 17, 2013
1 parent 28a2c68 commit e04553a
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 56 deletions.
2 changes: 1 addition & 1 deletion examples/todomvc/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var app = new Vue({

el: '#todoapp',

init: function () {
created: function () {
this.updateFilter()
this.remaining = this.todos.filter(function (todo) {
return !todo.completed
Expand Down
38 changes: 27 additions & 11 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function Compiler (vm, options) {
// so we should not run any transitions
compiler.init = true

// extend options
// process and extend options
options = compiler.options = options || makeHash()
utils.processOptions(options)
utils.extend(compiler, options.compilerOptions)
Expand Down Expand Up @@ -83,12 +83,13 @@ function Compiler (vm, options) {
// setup observer
compiler.setupObserver()

// call user init. this will capture some initial values.
if (options.init) {
options.init.apply(vm, options.args || [])
// pre compile / created hook
var created = options.beforeCompile || options.created
if (created) {
created.call(vm, options)
}

// create bindings for keys set on the vm by the user
// create bindings for things already in scope
var key, keyPrefix
for (key in vm) {
keyPrefix = key.charAt(0)
Expand Down Expand Up @@ -122,6 +123,12 @@ function Compiler (vm, options) {

// done!
compiler.init = false

// post compile / ready hook
var ready = options.afterCompile || options.ready
if (ready) {
ready.call(vm, options)
}
}

var CompilerProto = Compiler.prototype
Expand Down Expand Up @@ -557,14 +564,18 @@ CompilerProto.destroy = function () {

var compiler = this,
i, key, dir, instances, binding,
el = compiler.el,
directives = compiler.dirs,
exps = compiler.exps,
bindings = compiler.bindings,
teardown = compiler.options.teardown
vm = compiler.vm,
el = compiler.el,
directives = compiler.dirs,
exps = compiler.exps,
bindings = compiler.bindings,
beforeDestroy = compiler.options.beforeDestroy,
afterDestroy = compiler.options.afterDestroy

// call user teardown first
if (teardown) teardown()
if (beforeDestroy) {
beforeDestroy.call(vm)
}

// unwatch
compiler.observer.off()
Expand Down Expand Up @@ -619,6 +630,11 @@ CompilerProto.destroy = function () {
el.parentNode.removeChild(el)
}, this)
}

// post teardown hook
if (afterDestroy) {
afterDestroy.call(vm)
}
}

// Helpers --------------------------------------------------------------------
Expand Down
1 change: 0 additions & 1 deletion src/viewmodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ def(VMProto, '$emit', function () {
parent = compiler.parentCompiler
emitter.emit.apply(emitter, arguments)
if (parent) {
parent.emitter.emit.apply(parent.emitter, arguments)
parent.vm.$emit.apply(parent.vm, arguments)
}
})
Expand Down
2 changes: 1 addition & 1 deletion test/functional/fixtures/custom-element.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
},
// private custom element with constructor
wow: Vue.extend({
init: function () {
ready: function () {
this.$el.textContent = 'this is wow'
}
})
Expand Down
2 changes: 1 addition & 1 deletion test/functional/fixtures/nested-props.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ <h3>Computed property that concats the two: <span v-text="d"></span></h3>
var data = { c: 555 }
var Demo = Vue.extend({
lazy: true,
init: function () {
ready: function () {
this.msg = 'Yoyoyo'
this.a = data
},
Expand Down
2 changes: 1 addition & 1 deletion test/functional/fixtures/nested-viewmodels.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
Vue.config({ debug: true })

var Man = Vue.extend({
init: function () {
created: function () {
this.name = this.$el.dataset.name
var family = this.$el.dataset.family
if (family) {
Expand Down
2 changes: 1 addition & 1 deletion test/functional/fixtures/repeated-vms.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
Vue.config({ debug: true })

Vue.component('item', {
init: function () {
ready: function () {
this.item.title += ' init'
},
proto: {
Expand Down
111 changes: 81 additions & 30 deletions test/unit/specs/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,19 +338,6 @@ describe('UNIT: API', function () {

describe('Options', function () {

describe('init', function () {

it('should be called on the instance when instantiating', function () {
var called = false,
Test = Vue.extend({ init: function () {
called = true
}})
new Test({ el: document.createElement('div') })
assert.ok(called)
})

})

describe('proto', function () {

it('should be mixed to the exteded VM\'s prototype', function () {
Expand Down Expand Up @@ -451,7 +438,7 @@ describe('UNIT: API', function () {

})

describe('element options', function () {
describe('DOM element options', function () {

it('should not accept el as an extension option', function () {
var el = document.createElement('div'),
Expand Down Expand Up @@ -729,22 +716,6 @@ describe('UNIT: API', function () {

})

describe('teardown', function () {

it('should be called when a vm is destroyed', function () {
var called = false
var Test = Vue.extend({
teardown: function () {
called = true
}
})
var test = new Test()
test.$destroy()
assert.ok(called)
})

})

describe('transitions', function () {

it('should get called during transitions', function () {
Expand Down Expand Up @@ -790,6 +761,86 @@ describe('UNIT: API', function () {

})

describe('hooks', function () {

describe('beforeCompile / created', function () {

it('should be called before compile', function () {

var called = false,
Test = Vue.extend({ beforeCompile: function (options) {
assert.ok(options.ok)
called = true
}}),
Test2 = Vue.extend({ created: function (options) {
assert.ok(options.ok)
called = true
}})
new Test({ ok: true })
assert.ok(called)
called = false
new Test2({ ok: true })
assert.ok(called)
})

})

describe('afterCompile / ready', function () {

it('should be called after compile with options', function () {
var called = false,
hook = function (options) {
assert.ok(options.ok)
assert.notOk(this.$compiler.init)
called = true
},
Test = Vue.extend({ afterCompile: hook }),
Test2 = Vue.extend({ ready: hook })
new Test({ ok: true })
assert.ok(called)
called = false
new Test2({ ok: true })
assert.ok(called)
})

})

describe('beforeDestroy', function () {

it('should be called before a vm is destroyed', function () {
var called = false
var Test = Vue.extend({
beforeDestroy: function () {
called = true
}
})
var test = new Test()
test.$destroy()
assert.ok(called)
})

})

describe('afterDestroy', function () {

it('should be called after a vm is destroyed', function () {
var called = false,
Test = Vue.extend({
afterDestroy: function () {
assert.notOk(this.$el.parentNode)
called = true
}
})
var test = new Test()
document.body.appendChild(test.$el)
test.$destroy()
assert.ok(called)
})

})

})

})

})
Expand Down
23 changes: 14 additions & 9 deletions test/unit/specs/viewmodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe('UNIT: ViewModel', function () {
var triggered = 0,
msg = 'broadcast test'
var Child = Vue.extend({
init: function () {
ready: function () {
this.$on('hello', function (m) {
assert.strictEqual(m, msg)
triggered++
Expand All @@ -178,7 +178,7 @@ describe('UNIT: ViewModel', function () {
midTriggered = false,
msg = 'emit test'
var Bottom = Vue.extend({
init: function () {
ready: function () {
var self = this
setTimeout(function () {
self.$emit('hello', msg)
Expand All @@ -191,7 +191,7 @@ describe('UNIT: ViewModel', function () {
var Middle = Vue.extend({
template: '<div v-component="bottom"></div>',
components: { bottom: Bottom },
init: function () {
ready: function () {
this.$on('hello', function (m) {
assert.strictEqual(m, msg)
midTriggered = true
Expand All @@ -201,7 +201,7 @@ describe('UNIT: ViewModel', function () {
var Top = Vue.extend({
template: '<div v-component="middle"></div>',
components: { middle: Middle },
init: function () {
ready: function () {
this.$on('hello', function (m) {
assert.strictEqual(m, msg)
topTriggered = true
Expand All @@ -219,7 +219,8 @@ describe('UNIT: ViewModel', function () {
// that's what we are actually testing here.
var destroy = require('vue/src/compiler').prototype.destroy

var tearDownCalled = false,
var beforeDestroyCalled = false,
afterDestroyCalled = false,
observerOffCalled = false,
emitterOffCalled = false,
dirUnbindCalled = false,
Expand Down Expand Up @@ -265,8 +266,11 @@ describe('UNIT: ViewModel', function () {

var compilerMock = {
options: {
teardown: function () {
tearDownCalled = true
beforeDestroy: function () {
beforeDestroyCalled = true
},
afterDestroy: function () {
afterDestroyCalled = true
}
},
observer: {
Expand Down Expand Up @@ -312,8 +316,9 @@ describe('UNIT: ViewModel', function () {

destroy.call(compilerMock)

it('should call the teardown option', function () {
assert.ok(tearDownCalled)
it('should call the pre and post destroy hooks', function () {
assert.ok(beforeDestroyCalled)
assert.ok(afterDestroyCalled)
})

it('should turn observer and emitter off', function () {
Expand Down

0 comments on commit e04553a

Please sign in to comment.