mirror of https://github.com/vuejs/vue.git
				
				
				
			add teardown option; tests for $destroy()
This commit is contained in:
		
							parent
							
								
									c56cbdcc39
								
							
						
					
					
						commit
						5ffa301467
					
				|  | @ -65,12 +65,9 @@ module.exports = function( grunt ) { | |||
|         }, | ||||
| 
 | ||||
|         watch: { | ||||
|             options: { | ||||
|                 livereload: true | ||||
|             }, | ||||
|             component: { | ||||
|             dev: { | ||||
|                 files: ['src/**/*.js', 'component.json'], | ||||
|                 tasks: ['component_build'] | ||||
|                 tasks: ['component_build', 'jsc'] | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -556,31 +556,42 @@ CompilerProto.getOption = function (type, id) { | |||
|  *  Unbind and remove element | ||||
|  */ | ||||
| CompilerProto.destroy = function () { | ||||
|     var compiler = this | ||||
|     log('compiler destroyed: ', compiler.vm.$el) | ||||
|     // unwatch
 | ||||
|     compiler.observer.off() | ||||
|     compiler.emitter.off() | ||||
|     var i, key, dir, inss, binding, | ||||
| 
 | ||||
|     var compiler = this, | ||||
|         i, key, dir, instances, binding, | ||||
|         el         = compiler.el, | ||||
|         directives = compiler.dirs, | ||||
|         exps       = compiler.exps, | ||||
|         bindings   = compiler.bindings | ||||
|     // remove all directives that are instances of external bindings
 | ||||
|         bindings   = compiler.bindings, | ||||
|         teardown   = compiler.options.teardown | ||||
| 
 | ||||
|     // call user teardown first
 | ||||
|     if (teardown) teardown() | ||||
| 
 | ||||
|     // unwatch
 | ||||
|     compiler.observer.off() | ||||
|     compiler.emitter.off() | ||||
| 
 | ||||
|     // unbind all direcitves
 | ||||
|     i = directives.length | ||||
|     while (i--) { | ||||
|         dir = directives[i] | ||||
|         // if this directive is an instance of an external binding
 | ||||
|         // e.g. a directive that refers to a variable on the parent VM
 | ||||
|         // we need to remove it from that binding's instances
 | ||||
|         if (!dir.isSimple && dir.binding.compiler !== compiler) { | ||||
|             inss = dir.binding.instances | ||||
|             if (inss) inss.splice(inss.indexOf(dir), 1) | ||||
|             instances = dir.binding.instances | ||||
|             if (instances) instances.splice(instances.indexOf(dir), 1) | ||||
|         } | ||||
|         dir.unbind() | ||||
|     } | ||||
| 
 | ||||
|     // unbind all expressions (anonymous bindings)
 | ||||
|     i = exps.length | ||||
|     while (i--) { | ||||
|         exps[i].unbind() | ||||
|     } | ||||
| 
 | ||||
|     // unbind/unobserve all own bindings
 | ||||
|     for (key in bindings) { | ||||
|         if (hasOwn.call(bindings, key)) { | ||||
|  | @ -591,6 +602,7 @@ CompilerProto.destroy = function () { | |||
|             binding.unbind() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // remove self from parentCompiler
 | ||||
|     var parent = compiler.parentCompiler, | ||||
|         childId = compiler.childId | ||||
|  | @ -600,7 +612,8 @@ CompilerProto.destroy = function () { | |||
|             delete parent.vm.$[childId] | ||||
|         } | ||||
|     } | ||||
|     // remove el
 | ||||
| 
 | ||||
|     // finally remove dom element
 | ||||
|     if (el === document.body) { | ||||
|         el.innerHTML = '' | ||||
|     } else if (el.parentNode) { | ||||
|  |  | |||
|  | @ -500,6 +500,22 @@ describe('UNIT: API', function () { | |||
| 
 | ||||
|             }) | ||||
| 
 | ||||
|             describe('teardown', function () { | ||||
|                  | ||||
|                 it('should be called when a vm is destroyed', function () { | ||||
|                     var called = false | ||||
|                     var Test = Seed.extend({ | ||||
|                         teardown: function () { | ||||
|                             called = true | ||||
|                         } | ||||
|                     }) | ||||
|                     var test = new Test() | ||||
|                     test.$destroy() | ||||
|                     assert.ok(called) | ||||
|                 }) | ||||
| 
 | ||||
|             }) | ||||
| 
 | ||||
|             describe('transitions', function () { | ||||
|                 // it('should be tested', function () {
 | ||||
|                 //     assert.ok(false)
 | ||||
|  |  | |||
|  | @ -1,11 +1,3 @@ | |||
| /* | ||||
|  *  Only tests the following: | ||||
|  *  - .$get() | ||||
|  *  - .$set() | ||||
|  *  - .$watch() | ||||
|  *  - .$unwatch() | ||||
|  */ | ||||
| 
 | ||||
| describe('UNIT: ViewModel', function () { | ||||
| 
 | ||||
|     mock('vm-test', '{{a.b.c}}') | ||||
|  | @ -227,4 +219,144 @@ describe('UNIT: ViewModel', function () { | |||
| 
 | ||||
|     }) | ||||
| 
 | ||||
|     describe('.$destroy', function () { | ||||
|          | ||||
|         // since this simply delegates to Compiler.prototype.destroy(),
 | ||||
|         // that's what we are actually testing here.
 | ||||
|         var destroy = require('seed/src/compiler').prototype.destroy | ||||
| 
 | ||||
|         var tearDownCalled = false, | ||||
|             observerOffCalled = false, | ||||
|             emitterOffCalled = false, | ||||
|             dirUnbindCalled = false, | ||||
|             expUnbindCalled = false, | ||||
|             bindingUnbindCalled = false, | ||||
|             unobserveCalled = 0, | ||||
|             elRemoved = false, | ||||
|             externalBindingUnbindCalled = false | ||||
| 
 | ||||
|         var dirMock = { | ||||
|             binding: { | ||||
|                 compiler: null, | ||||
|                 instances: [] | ||||
|             }, | ||||
|             unbind: function () { | ||||
|                 dirUnbindCalled = true | ||||
|             } | ||||
|         } | ||||
|         dirMock.binding.instances.push(dirMock) | ||||
| 
 | ||||
|         var bindingsMock = Object.create({ | ||||
|             'test2': { | ||||
|                 unbind: function () { | ||||
|                     externalBindingUnbindCalled = true | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         bindingsMock.test = { | ||||
|             root: true, | ||||
|             key: 'test', | ||||
|             value: { | ||||
|                 __observer__: { | ||||
|                     off: function () { | ||||
|                         unobserveCalled++ | ||||
|                         return this | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             unbind: function () { | ||||
|                 bindingUnbindCalled = true | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         var compilerMock = { | ||||
|             options: { | ||||
|                 teardown: function () { | ||||
|                     tearDownCalled = true | ||||
|                 } | ||||
|             }, | ||||
|             observer: { | ||||
|                 off: function () { | ||||
|                     observerOffCalled = true | ||||
|                 }, | ||||
|                 proxies: { | ||||
|                     'test.': {} | ||||
|                 } | ||||
|             }, | ||||
|             emitter: { | ||||
|                 off: function () { | ||||
|                     emitterOffCalled = true | ||||
|                 } | ||||
|             }, | ||||
|             dirs: [dirMock], | ||||
|             exps: [{ | ||||
|                 unbind: function () { | ||||
|                     expUnbindCalled = true | ||||
|                 } | ||||
|             }], | ||||
|             bindings: bindingsMock, | ||||
|             childId: 'test', | ||||
|             parentCompiler: { | ||||
|                 childCompilers: [], | ||||
|                 vm: { | ||||
|                     $: { | ||||
|                         'test': true | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             el: { | ||||
|                 parentNode: { | ||||
|                     removeChild: function () { | ||||
|                         elRemoved = true | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         compilerMock.parentCompiler.childCompilers.push(compilerMock) | ||||
| 
 | ||||
|         destroy.call(compilerMock) | ||||
| 
 | ||||
|         it('should call the teardown option', function () { | ||||
|             assert.ok(tearDownCalled) | ||||
|         }) | ||||
| 
 | ||||
|         it('should turn observer and emitter off', function () { | ||||
|             assert.ok(observerOffCalled) | ||||
|             assert.ok(emitterOffCalled) | ||||
|         }) | ||||
| 
 | ||||
|         it('should unbind all directives', function () { | ||||
|             assert.ok(dirUnbindCalled) | ||||
|         }) | ||||
| 
 | ||||
|         it('should remove directives from external bindings', function () { | ||||
|             assert.strictEqual(dirMock.binding.instances.indexOf(dirMock), -1) | ||||
|         }) | ||||
| 
 | ||||
|         it('should unbind all expressions', function () { | ||||
|             assert.ok(expUnbindCalled) | ||||
|         }) | ||||
| 
 | ||||
|         it('should unbind and unobserve own bindings', function () { | ||||
|             assert.ok(bindingUnbindCalled) | ||||
|             assert.strictEqual(unobserveCalled, 3) | ||||
|         }) | ||||
| 
 | ||||
|         it('should not unbind external bindings', function () { | ||||
|             assert.notOk(externalBindingUnbindCalled) | ||||
|         }) | ||||
| 
 | ||||
|         it('should remove self from parentCompiler', function () { | ||||
|             var parent = compilerMock.parentCompiler | ||||
|             assert.ok(parent.childCompilers.indexOf(compilerMock), -1) | ||||
|             assert.strictEqual(parent.vm.$[compilerMock.childId], undefined) | ||||
|         }) | ||||
| 
 | ||||
|         it('should remove the dom element', function () { | ||||
|             assert.ok(elRemoved) | ||||
|         }) | ||||
| 
 | ||||
|     }) | ||||
| 
 | ||||
| }) | ||||
		Loading…
	
		Reference in New Issue