扩展Backbone.View

时间:2014-10-09 23:41:27

标签: javascript class backbone.js prototype

我试图扩展我的Backbone.View类。 最初我提出了创建自己的界面的想法,以简化删除childViews所需的代码量。

基本上,一个数组和一些方法迭代数组上的每个视图,为每个视图调用remove。这对列表等事情特别有用。

然后我尝试了类似的东西,并意识到从类创建的对象在其属性上共享相同的实例。

Backbone.SuperView = Backbone.View.extend({
  childViews: ['global']
})


var App_View = Backbone.SuperView.extend({
   initialize: function(options){
       this.childViews.push(options.viewName);
console.log('app_View =>' + this.childViews);
   }
})

var App2_View = Backbone.SuperView.extend({
   initialize: function(options){
       this.childViews.push(options.viewName);
console.log('app2_View =>' + this.childViews);
   }
})

new App_View({viewName: 'a'});
new App2_View({viewName: 'b'});

输出:

app_View =>  global ,a 
app2_View => global ,a ,b

我不想在我从Backbone.SuperView创建的所有对象中使用相同的childViews实例!就像你可以想象我假装在从该类创建的所有对象中都有一个数组childViews但我有不同的内存实例,所以每个视图都有它自己的子视图。

然后我想出了以下概念,但我仍然认为这不是正确的做事方式:

我的概述课程

;(function($, _ , Backbone) {
   'use strict';

   Backbone.SuperView = Backbone.View.extend({
      initialize: function(){
         this._views = {};
         this._listViews = [];
         this._bindedElements = [];

         _.extend(this,
            {
            _destoryAllViews: function(){
               this._removeListViews();
               this._removeViews();
               this.remove();
            },
            // destroy a view atual e as subviews e listviews
            destroy: function(options){
               options = options || {};
               var defaults = {timeout : 200};
               if (_.isEmpty(options)){
                  options = defaults;

                  setTimeout($.proxy(function(){
                     this._destoryAllViews();
                     this._cleanExternalEventBinds();
                  },this), options.timeout );
               } else {
                  this._destoryAllViews();
                  this._cleanExternalEventBinds();
               }
            },
            addListView: function(view){
               this._listViews.push(view);
            },
            // manual view cleaner
            emptyListView: function(destroy){
                this._removeListViews();
            },
            /*
               views with same keys are destroyed and then assigned
            */
            set: function(key, view, options){
               options = options || {};
               var destroy = ('destroy' in options ) ? options.destroy : true;

               if (key in this._views){
                  this._views[key].view.destroy();
               }

               this._views[key] = { 'view': view, 'destroy':  destroy };

               return view;
            },
            get: function(key){
               return this._views[key].view;
            },
            _removeViews: function(){
               _.each( this._views, function( viewSettings ){
                  if (viewSettings.destroy){
                     if (viewSettings.view.destroy){
                        viewSettings.view.destroy();
                     }
                  }
               });
            },
            _removeListViews: function(){
               _.each( this._listViews, function( view ){
                  if (view.destroy){
                     view.destroy();
                  }
               });
            },
            setEvent: function(el, eventName, callback){
               var $el = $(el),
                  callback = (_.isFunction(callback)) ? callback : this[callback];

                  $el.bind(eventName + '.' + this.cid, callback);

               this._bindedElements.push(el);
            },
            _cleanExternalEventBinds: function(){
               var _that = this;
               _.each(this._bindedElements, function(el){
                  el.off('.' + _that.cid );
               });
            }

         });

      }
   });


   //_.extend(Backbone.SuperView.prototype, )


   return Backbone;

})($, _ , Backbone);

我的HTML

<a href="#" class="my-btn">My-btn</a>
<div class="app-placeholder"></div>

MY SCIRPT

var c = Backbone.Collection.extend({});

        var C = new c([{
            name: 'Frank',
            age: 12
        },
        {
            name: 'Maria',
            age: 19
        },
        {
            name: 'Richard',
            age: 20
        }])

        var header_View = Backbone.SuperView.extend({
            events: {
                'click': 'log'
            },
            initialize: function(){
                Backbone.SuperView.prototype.initialize.call(this);
                this.$mybtn = $('.my-btn');
                this.setEvent(this.$mybtn, 'click', function(e){
                    e.preventDefault();
                    alert('hello');
                });
                this.setEvent(this.$mybtn, 'click', 'innerHello')
                // this.setEvent(this.$mybtn, 'click', 'log')
                this.$el.append('<h1>My Header</h1>')
                return this;
            },
            innerHello: function(e){
                // e.preventDefault();
                alert('hello 2');
            },
            log: function(){
                console.log(this._bindedElements);
            }
        });

        var item = Backbone.SuperView.extend({
            template: _.template('<%= age %>||<%=name%>'),
            events: {
                'click': 'log'
            },
            initialize: function(options){
                Backbone.SuperView.prototype.initialize.call(this);
                this.model = options.model;
                this.render();
            },
            render: function(){
                this.$el.html('').append(this.template(this.model.toJSON()))
            },
            log: function(){
                console.log(this._bindedElements);
            }
        })

        var b = Backbone.SuperView.extend({
            initialize: function(){
                Backbone.SuperView.prototype.initialize.call(this);
                this.set('myView', new header_View());
                this.$el.html( '' ).append( this.get('myView').el );
                this.collection = C;
                this.render();
            },
            render: function(){
                this.emptyListView();
                this.addAll();
            },
            addAll: function(){
                this.collection.forEach(function(model){
                    var _item = new item({model:model});
                    this.addListView(  _item );
                    this.$el.append( _item.el );
                },this)
            }
        })

        var m = Backbone.View.extend({
            initialize: function(){

            },
        })

        var B = new b();
        $('.app-placeholder').append(B.el);

这感觉不对,我正在寻找更加可靠的解决方案。 我是否真的必须在每个视图中调用初始值设定项?

上面的代码是这样的:

  1. 运行该脚本将呈现3个项目和标题的列表。

  2. header_view使用我自己创建的方法将事件绑定到视图外的DOM元素

  3. 它将dom元素插入到数组中,稍后,当元素被销毁时,事件也会从该全局元素中分离,从而防止内存和事件发生。

  4. 在上述情况下,只需点击header_view就会输出_bindedElements中的有界元素,因为iniside header_View初始化我调用this.setEvent($ el,&#39; eventName&#39;,callback)

    < / LI>

0 个答案:

没有答案