7

Tôi đang kéo tóc ra, dường như tôi không nhận được sự kiện chuột để hoạt động trên chế độ xem xương sống của mình sau khi chế độ xem được hiển thị lại trừ khi tôi làm điều vô lý nhất:sự kiện xem xương sống không hoạt động sau khi hiển thị lại

$("a").die().unbind().live("mousedown",this.switchtabs); 

Tôi thực sự có điều này trong đó nhưng đã quyết định cập nhật lên xương sống mới nhất và cố gắng sử dụng chức năng delegateEvents() mới.

Dưới đây là cách id dự án của tôi có cấu trúc:

Appview/AppRouter 
    | 
    ----->PageCollection 
      | 
      ------->PageView/PageModel 
      ------->PageView/PageModel  these page view/models are not rendered 
      ------->PageView/PageModel 
      | 
      ------->PageView/PageModel 
         | 
         ----->render()  *when a pageview is rendered* 
           | 
           -----> Creates new 
            Tabcollection 
             | 
             --->TabModel/TabView <-- this is where the issue is 

gì xảy ra là tabcollection có TabView chính để quản lý tất cả các tab, sau đó tạo ra một mô hình mới/xem cho mỗi tab và đặt một người nghe sẽ trả lại tabview bất cứ khi nào một tab được tải. Nếu tabview được trả lại, không có sự kiện chuột nào hoạt động nữa trừ khi tôi đặt câu lệnh jQuery giả tạo trong đó.

Heres TabView và render (ive lột nó xuống khá một chút)

var TabPanelView = Backbone.View.extend({ 
    className:  "tabpanel", 
    html:   'no content', 
    model:   null, 
    rendered:  false, 
    events:{ 
     'click a.tab-nav': 'switchtabs' 
    }, 
    initialize: function(args) 
    { 
     this.nav   = $("<ol/>"); 
     this.views   = args.items; 
     this.className  = args.classname?args.classname:"tabpanel"; 
     this.id    = args.id; 
     this.container  = $("<section>").attr("class",this.className).attr("id",this.id); 
     _.bindAll(this); 
     return this.el 
    }, 
    /* 
    This render happens multiple times, the first time it just puts an empty html structure in place 
    waiting for each of the sub models/views to load in (one per tab) 
    */ 
    render: function(args){ 
     if(!args) 
     { 
      //first render 
      var nav    = $("<aside/>").addClass("tab-navigation").append("<ol/>").attr("role","navigation"); 
      var tabcontent  = $("<section/>").addClass("tab-panels"); 
      for(i = 0;i<this.views.length;i++) 
      { 
       $("ol",nav).append("<li><a rel='"+this.views[i].id+"' href='javascript:;' class='tab-nav'></a></li>"); 
       tabcontent.append(this.views[i].el); 
      } 
      this.$el.empty().append(nav).append(tabcontent); 
     } 
     else if(args && args.update == true){ 
      // partial render -- i.e. update happened inside of child objects 
      var targetid = args.what.cid; 
      for(i = 0;i<this.views.length;i++) 
      { 
       var curcontent = this.$el.find("div#"+this.views[i].id); 
       var curlink  = this.$el.find("a[rel='"+this.views[i].id+"']") 
       if(this.views[i].cid == targetid) 
       { 
        curcontent.html($(this.views[i].el).html()); 
        curlink.text(this.views[i].model.rawdata.header); 
       } 
       if(i>0) 
       { 
        // set the first panel 
        curcontent.addClass("tab-content-hide"); 
       } 
       if(i==0) 
       { 
        curcontent.addClass("tab-content-show"); 
        curlink.addClass("tab-nav-selected"); 
       } 
       // this ridiculous piece of jQuery is the *ONLY* this i've found that works 
       //$("a[rel='"+this.views[i].id+"']").die().unbind().live("mousedown",this.switchtabs); 
      } 
     } 
     this.delegateEvents(); 
     return this; 
    }, 
    switchtabs: function(args){ 

     var tabTarget = args.target?args.target:false 
     if(tabTarget) 
     { 
      this.$el.find("aside.tab-navigation a").each(function(a,b) 
      { 
       $(this).removeClass("tab-nav-selected") 
      }) 
      $(tabTarget).addClass("tab-nav-selected"); 
      this.$el.find("div.tab-content-show").removeClass("tab-content-show").addClass("tab-content-hide"); 
      this.$el.find("div#"+tabTarget.rel).removeClass("tab-content-hide").addClass("tab-content-show"); 
     } 
    } 
}); 

bất cứ ai có thể nghĩ ra lý do tại sao sự kiện xương sống chuột đơn giản là không bắn ở tất cả, chẳng qua là vì họ không trên DOM ? Tôi nghĩ rằng đây là nơi xương sống đặc biệt hữu ích? ...

+0

Bạn đã thực hiện các bước nào để khắc phục sự cố này cho đến thời điểm này? Một vài điều tôi sẽ thử: Xem bạn có thể thiết lập một điểm ngắt trong nguồn Backbone khi phần tử 'events' được xử lý hay không. Có thể cung cấp cho bạn một số thông tin chi tiết. Ngoài ra, hãy thử sử dụng các điểm ngắt DOM và Trình nghe sự kiện của Chrome. Điều này có thể giúp bạn kiểm tra xem có bất kỳ mã nào đang được thực thi hay không hoặc nếu các sự kiện không kết nối được. –

+0

Ive đăng nhập với jq $ (tài liệu) .find ("tab-nav-selected") để xem các mục được hiển thị có thực sự trên dom .. tốt có được kết quả đúng hay không. đã đi qua các điểm ngắt, trong mã của riêng tôi. Tôi không đủ tự tin với nó để đi đào trong chính xương sống với trình gỡ lỗi. phạm vi tất cả có vẻ tốt ... Tôi không chắc chắn bằng bất kỳ phương tiện nhưng có vẻ như là mặc dù các sự kiện hoặc là bị ghi đè do tái rendering hoặc ... ummm – Alex

Trả lời

6

dòng mã này có khả năng vấn đề của bạn:

this.delegateEvents();

Xóa mục đó và nó sẽ hoạt động.

Lần duy nhất bạn cần tự gọi delegateEvents, là khi bạn có các sự kiện được khai báo riêng biệt với mã băm events của chế độ xem của bạn. Khung nhìn của Backbone sẽ gọi phương thức này cho bạn khi bạn tạo một thể hiện của khung nhìn.

+0

thật đáng buồn là không có súc sắc. hân hạnh được bạn trả lời, tôi đã đọc một loạt các nội dung có ích trên blog của bạn. Tôi đã đưa vào và đi với jQuery.live ... có, đó là một abomination .. nhưng đó là điều duy nhất làm việc và tôi đã có 2 ngày đến hạn chót .. humm – Alex

2

Khi chế độ xem được hiển thị lại, bạn đang sử dụng lại chế độ xem đó và chỉ gọi lại() trên đó hoặc bạn đang xóa chế độ xem và tạo ra một cái nhìn hoàn toàn mới?

Dù bằng cách nào, có vẻ như nguyên nhân là do các sự kiện chế độ xem không bị ràng buộc trước khi chế độ xem được hiển thị lại. Derick Bailey có số lượng lớn post về việc này.

Khi bạn tái render, 1) chắc chắn rằng bạn unbind tất cả các sự kiện trong giao diện cũ và 2) tạo ra một cái nhìn mới và làm cho nó

+0

bài viết tốt đẹp tuy nhiên tôi không thể đi làm mới xem cha mẹ khi mọi lượt xem con cập nhật (chế độ xem gốc phải trả lời chế độ xem con). Kỳ lạ là tôi đã thử phương pháp trong bài viết tuy nhiên nó làm việc khoảng 1 lần trong mỗi 3 lần tôi tải lại trang lần khác ... không có gì – Alex

1

Khi sử dụng $(el).empty() nó loại bỏ tất cả các phần tử con trong thành phần được chọn VÀ loại bỏ TẤT CẢ các sự kiện (và dữ liệu) mà bị ràng buộc với bất kỳ (trẻ em) yếu tố bên trong của phần tử được lựa chọn (el).

Để giữ các sự kiện ràng buộc để các yếu tố con, nhưng vẫn loại bỏ các phần tử con, sử dụng:

$(el).children().detach(); thay vì $(.el).empty();

này sẽ cho phép bạn xem để rerender thành công với các sự kiện vẫn còn bị ràng buộc và làm việc.

+1

@Alex Trong mã của bạn hãy thử: '' này $ el.children(). detach(). append (nav) .append (tabcontent); '' và nó sẽ ** làm việc ** hoàn hảo. Không cần phải tạo lại một thể hiện của khung nhìn. – AmpT

+0

Vui lòng xem các câu trả lời sau để tham khảo thêm: http://stackoverflow.com/a/12029250/2728686 và http://stackoverflow.com/a/7417078/2728686 – AmpT

Các vấn đề liên quan