2013-01-16 72 views
1

我試圖創建一個動態的Widget系統來在我的頁面內創建面板。 讓我們把一個簡單的例子:骨幹:使用_.template內的視圖

   Widgets.create({ 
        name : 'menu-site', 
        title: 'Menu', 
        content: 'This is my menu!' 
       }); 

,它將使這樣的:

<section class="widget menu-site"> 
    <h1>Menu</h1> 
    <article>This is my menu!</article> 
</section> 

其確定正確的?我做了一千次。

   var view = new MyCustomView;     
       Widgets.create({ 
        name : 'custom-panel', 
        title: 'Custom Panel', 
        content: view.render().el 
       });      

我可以通過調用WidgetView內outerHTML,但是,當我做到這一點,裏面MyCustomView聲明的事件不工作呈現內容: 但是,當我嘗試使用內部的視圖的問題開始!

有人曾經遇到過這個問題嗎?

對於那些誰需要更多的細節,這是我WidgetView代碼:

 var Widget = Backbone.Model.extend({ 
      defaults : function() { 
       return { 
        title : '', 
        content : '', 
        closeable : true 
       } 
      } 
     }); 
     var WidgetList = Backbone.Collection.extend({ 
      url : '/widgets', 
      model : Widget 
     }); 
     Widgets = new WidgetList; 


     var WidgetView = Backbone.View.extend({ 
      tagName : 'section', 
      className : function() { 
       return ['widget',' ', this.model.get('name')].join(''); 
      }, 
    template: _.template($('#widget-template').html()), 

      events : { 
       "click .close" : "removeWidget" 
      }, 

      initialize : function() { 
       this.listenTo(this.model, 'destroy', this.remove); 
      }, 


      removeWidget : function() { 
       this.model.destroy(); 
      }, 

      render: function() { 
       this.$el.append(this.template(this.model.toJSON())); 
       return this; 
      }, 
     }); 

     var AppViewport = Backbone.View.extend({ 
      el : $("#widgets"), 

      events : { 
      }, 

      initialize : function() { 
       this.listenTo(Widgets, 'add', this.addNewWidgetView); 
      }, 

      addNewWidgetView : function(widget) { 
       var view = new WidgetView({model: widget}); 
       this.$el.append(view.render().el); 
      } 
     }); 

     new AppViewport; 

或許,即時通訊想着其他辦法解決這個.. 但我浪費了那麼多時間去理解這個問題,我只是不能看到光!

UPDATE --------------- 18/01 ---------

我做了一些測試,並改變了我的代碼: 相反使用下劃線模板,我創建了一個WidgetViewLayout,並做了所有手工模板工作:

  var WidgetView = Backbone.View.extend({ 
       tagName : 'section', 
       className : function() { 
        return ['widget',' ', this.model.get('name')].join(''); 
       }, 

       events : { 
        "click .close" : "removeWidget" 
       }, 

       initialize : function() { 
        this.listenTo(this.model, 'destroy', this.remove); 
       }, 


       removeWidget : function() { 
        this.model.destroy(); 
        MenuRouterInstance.navigate(''); 
       }, 

       render: function() { 
        var layout_view = new WidgetViewLayout({model: this.model.toJSON()}); 
        this.$el.append(layout_view.render().el); 
        return this; 
       } 
      }); 

      var WidgetViewLayout = Backbone.View.extend({ 
       tagName : 'div', 

       render : function() { 
        var title = this.model.title, 
         content = this.model.content, 
         closeable = this.model.closeable || false; 

        var anchor = this.setupAnchor(closeable), 
         h1 = this.setupH1(title, anchor), 
         article = this.setupArticle(content); 

        this.$el.append(h1); 
        this.$el.append(article); 

        return this; 
       }, 

       setupH1 : function(title, target) { 
        var element = $('<h1 />'); 
        element.text(title); 
        element.append(target); 

        return element; 
       }, 

       setupAnchor : function(closeable) { 
        var element = ''; 
        if(closeable == true) { 
         element = $('<a />'); 
         element.addClass('close'); 
         element.text('(fechar)'); 
        } 

        return element; 
       }, 

       setupArticle : function(content) { 
        var element = $('<article />'); 
        element.append(content); 

        return element; 
       } 
      }) 

似乎現在的工作,但我仍然有一些問題,我的小工具中創建的意見,這樣的:

    var view = new MyView;     
        Widgets.create({ 
         name : 'menu', 
         title: 'My menu', 
         content: view.render().el 
        }); 

當MyView在它自己內部創建多個SubView時,我調用model.destroy刪除其中一個子視圖的模型時,偵聽的方法「this.remove」最終刪除所有SubView,而不是僅刪除一個。最後,我被迫做到這一點:

   removeit : function(removed_item) { 
        if(removed_item.get('name') == this.model.get('name')) { 
         this.remove();        
        } 
       }, 

我不知道它的壞模式,但它已經奏效! 我很感激,如果有人有一個更好的主意!

] [`,S

回答

3

我覺得你的問題是,你試圖把一個DOM元素對象(el)作爲一個字符串。當你這樣做:

content: view.render().el 

你就會有一個活DOM節點content和視圖的事件將被綁定到該DOM節點。您可以使用其中一種HTML方法(在您的案例中顯然爲outerHTML)通過您的模板獲取節點的HTML,但處理事件的delegate綁定到DOM節點,而不是綁定到最終使用的HTML字符串。

您可以修改您的render以便在必要時按原樣處理原始DOM節點,像這樣。

render: function() { 
    var json = this.model.toJSON(); 
    if(_(json.content).isString()) { 
     this.$el.append(this.template(json)); 
    } 
    else { 
     var content = json.content; 
     delete json.content; 
     this.$el.append(this.template(json)); 
     this.$('article').append(content); 
    } 
} 

基本上,如果你的content不是一個字符串,然後把你的$el手動,而不是通過模板去。

+0

Humm,我明白了,但問題是:下劃線模板不允許我傳遞DOM節點。我必須先解析成HTML字符串。所以,正如你可以看到上面的更新,我決定用手動dom創建替換下劃線模板。 –

+0

堅持使用模板但不同類型的'content'有什麼不同? –