Explorar el Código

Detach model listeners on View destroy.

Aleksander Nowodzinski hace 10 años
padre
commit
fc052a7712
Se han modificado 2 ficheros con 44 adiciones y 9 borrados
  1. 7 4
      packages/ckeditor5-ui/src/ui/view.js
  2. 37 5
      packages/ckeditor5-ui/tests/ui/view.js

+ 7 - 4
packages/ckeditor5-ui/src/ui/view.js

@@ -83,7 +83,7 @@ CKEDITOR.define( [
 				// TODO: Use ES6 default arguments syntax.
 				callback = callback || domUpdater;
 
-				var listenerCallback = ( el, value ) => {
+				var listenerCallback = ( evt, value ) => {
 					var processedValue = callback( el, value );
 
 					if ( typeof processedValue != 'undefined' ) {
@@ -92,11 +92,11 @@ CKEDITOR.define( [
 				};
 
 				// Execute callback when the property changes.
-				model.on( 'change:' + property, ( evt, value ) => listenerCallback( el, value ) );
+				this.listenTo( model, 'change:' + property, listenerCallback );
 
 				// Set the initial state of the view.
-				listenerCallback( el, model[ property ] );
-			};
+				listenerCallback( null, model[ property ] );
+			}.bind( this );
 		}
 
 		/**
@@ -141,6 +141,9 @@ CKEDITOR.define( [
 			for ( let i = this.regions.length; i--; ) {
 				this.regions.remove( i ).destroy();
 			}
+
+			// Remove all listeners related to this view.
+			this.stopListening();
 		}
 	}
 

+ 37 - 5
packages/ckeditor5-ui/tests/ui/view.js

@@ -166,9 +166,17 @@ describe( 'render', function() {
 	} );
 } );
 
-describe( 'destroys', function() {
-	it( 'destroys the view', function() {
-		view = new TestView( { a: 1 } );
+describe( 'destroy', function() {
+	it( 'detaches the model', function() {
+		expect( view.model ).to.be.an.instanceof( modules.model );
+
+		view.destroy();
+
+		expect( view.model ).to.be.null;
+	} );
+
+	it( 'detaches the element', function() {
+		view = new TestView();
 
 		// Append the views's element to some container.
 		var container = document.createElement( 'div' );
@@ -177,13 +185,11 @@ describe( 'destroys', function() {
 		expect( view.el.nodeName ).to.be.equal( 'A' );
 		expect( view.el ).to.be.an.instanceof( HTMLElement );
 		expect( view.el.parentNode ).to.be.equal( container );
-		expect( view.model ).to.be.an.instanceof( modules.model );
 
 		view.destroy();
 
 		expect( view.el ).to.be.an.instanceof( HTMLElement );
 		expect( view.el.parentNode ).to.be.null;
-		expect( view.model ).to.be.null;
 	} );
 
 	it( 'destroys child regions', function() {
@@ -197,6 +203,32 @@ describe( 'destroys', function() {
 		expect( view.regions ).to.have.length( 0 );
 		expect( spy.calledOnce ).to.be.true;
 	} );
+
+	it( 'detaches bound model listeners', function() {
+		class TestView extends View {
+			constructor( model ) {
+				super( model );
+
+				this.template = {
+					tag: 'p',
+					text: this.bind( 'foo' )
+				};
+			}
+		}
+
+		view = new TestView( { foo: 'bar' } );
+		var model = view.model;
+
+		expect( view.el.outerHTML ).to.be.equal( '<p>bar</p>' );
+
+		model.foo = 'baz';
+		expect( view.el.outerHTML ).to.be.equal( '<p>baz</p>' );
+
+		view.destroy();
+
+		model.foo = 'abc';
+		expect( view.el.outerHTML ).to.be.equal( '<p>baz</p>' );
+	} );
 } );
 
 function createViewInstance() {