2012-02-02 17 views
12

He intentado adjuntar un controlador al evento de cambio de tamaño en una de mis vistas de Backbone. Después de investigar un poco, descubrí que solo puedes adjuntar eventos al elemento de la vista o a sus descendientes.¿Cómo agrego un evento de cambio de tamaño a la ventana en una vista usando Backbone?

Esto es un problema para mí porque el efecto visual que estoy tratando de lograr no es posible usando CSS puro y requiere algunas JS para establecer las dimensiones del elemento del área de contenido menos el elemento de encabezado.

Si tiene problemas para visualizar lo que estoy tratando de hacer, imaginar una cabecera delgada y un área de contenido que debe ocupar el espacio que queda sin CSS fondo engaño;)

He adjuntado un ejemplo de código. Si tienes otros indicadores, ¡también me encantaría escucharlos!

define(
    [ 
     'jQuery', 
     'Underscore', 
     'Backbone', 
     'Mustache', 
     'text!src/common/resource/html/base.html' 
    ], 
    function ($, _, Backbone, Mustache, baseTemplate) { 
     var BaseView = Backbone.View.extend({ 

      el: $('body'), 

      events: { 
       'resize window': 'resize' 
      }, 

      render: function() { 
       var data = {}; 

       var render = Mustache.render(baseTemplate, data); 

       this.$el.html(render); 

       this.resize(); 
      }, 

      resize: function() { 
       var windowHeight = $(window).height(); 

       var headerHeight = this.$el.find('#header').height(); 

       this.$el.find('#application').height(windowHeight - headerHeight); 
      } 
     }); 

     return new BaseView; 
    } 
); 

Cualquier ayuda sería muy apreciada por mi cara.

Gracias, Alex

Respuesta

25
var BaseView = Backbone.View.extend({ 

    el: $('body'), 

    initialize: function() { 
     // bind to the namespaced (for easier unbinding) event 
     // in jQuery 1.7+ use .on(...) 
     $(window).bind("resize.app", _.bind(this.resize, this)); 
    }, 

    remove: function() { 
     // unbind the namespaced event (to prevent accidentally unbinding some 
     // other resize events from other code in your app 
     // in jQuery 1.7+ use .off(...) 
     $(window).unbind("resize.app"); 

     // don't forget to call the original remove() function 
     Backbone.View.prototype.remove.call(this); 
     // could also be written as: 
     // this.constructor.__super__.remove.call(this); 
    }, ... 

No se olvide de llamar a la función remove() en la vista. Nunca solo reemplace la vista con otra.

+0

Gracias por su rápida respuesta! ¿Pero es una mala práctica salir de la capa de eventos de Backbone? –

+1

Yo diría que no te preocupes demasiado. El evento de cambio de tamaño no hace ninguna interacción compleja con tu estructura MVC por lo que no estás perdiendo nada con solo tener un escucha por separado – wheresrhys

+0

Gracias por aclarar eso para mí –

4

Puede dejar que window.onresize desencadene un evento personalizado y luego permita que las vistas o los modelos escuchen eso para tener respuestas personalizadas para varios elementos.

Caso 1. Una vista escucha el evento de ventana directamente.

window.onload = function() { 

    _.extend(window, Backbone.Events); 
    window.onresize = function() { window.trigger('resize') }; 

    ViewDirect = Backbone.View.extend({ 

    initialize: function() { 
     this.listenTo(window, 'resize', _.debounce(this.print)); 
    }, 

    print: function() { 
     console.log('Window width, heigth: %s, %s', 
     window.innerWidth, 
     window.innerHeight); 
    }, 

    }); 

    var myview = new ViewDirect(); 

    } 

Caso 2. Es posible que desee mantener el tamaño de la ventana sin inspeccionar cada vez que lo necesita, por lo tanto, permite almacenar el tamaño de la ventana en un modelo de columna vertebral: en este caso el modelo de ventana escucha la ventana , mientras que la vista escucha el modelo de ventana:

window.onload = function() { 

    _.extend(window, Backbone.Events); 
    window.onresize = function() { window.trigger('resize') }; 

    WindowModel = Backbone.Model.extend({ 

    initialize: function() { 
     this.set_size(); 
     this.listenTo(window, 'resize', _.debounce(this.set_size)); 
    }, 

    set_size: function() { 
     this.set({ 
     width: window.innerWidth, 
     height: window.innerHeight 
     }); 
    } 

    }); 

    ViewWithModel = Backbone.View.extend({ 

    initialize: function() { 
     this.listenTo(this.model, 'change', this.print); 
     ... 
    }, 

    print: function() { 
     console.log('Window width, heigth: %s, %s', 
     this.model.width, 
     this.model.height); 
    }, 
    }); 

    var window_model = new WindowModel(); 
    var myview = new ViewWithModel({model: window_model}); 

} 
+0

¿Hay alguna razón por la cual el modelo está involucrado en este proceso de evento? Normalmente pienso en el cambio de tamaño como un evento de capa de vista. – mlibby

+0

@mlibby depende de lo que está cambiando. Es posible que el evento cambie el modelo para que la vista solo tenga que ver con los eventos del modelo. – prodaea

+1

Hola, @mlibby. Disculpa por la repetición tardía. No noté tu pregunta. Editado para responder, también para comentar lo que dice prodaea arriba. –

Cuestiones relacionadas