2011-12-22 19 views
17

Chúng ta đều biết làm một cái gì đó như thế này là xấu:Ủy nhiệm các sự kiện để phụ quan điểm trong Backbone.js

<ul> 
    <li>Item</li> 
    <li>Item</li> 
    ... 500 more list items 
</ul> 

và sau đó ...

$("ul li").bind("click", function() { ... }); 

Tôi đã nhìn qua rất nhiều của các ví dụ/hướng dẫn Backbone và những điều sau đây có vẻ là một cách tiếp cận tiêu chuẩn để hiển thị một danh sách với các mục, dựa trên một tập hợp các mô hình.

var ListView = Backbone.View.extend() { 

    tagName: 'ul', 

    render: function() { 
    this.collection.each(function(item) { 
     var view = new ListItemView({model: item}); 
     $(this.el).append(view.render().el); 
    }); 
    return this; 
    } 
}); 

Một xem danh sách mục:

var ListItemView = Backbone.View.extend() { 

    tagName: 'li', 

    events: { 
    'click' : 'log' 
    } 

    log : function() { 
    console.log(this.model.get("title")); 
    } 

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

Nếu tôi không nhầm, instantiating ListView với một bộ sưu tập với 500 mô hình, mang lại cho tôi 500 sự kiện nhấp chuột, một cho mỗi hàng. Điều này là xấu phải không?

Tôi biết Backbone đã xây dựng trong đoàn sự kiện cho sự kiện namespaced:

events : { 
    'click li' : 'log' 
} 

Tôi cho rằng tôi có thể đặt điều này trong ListView của tôi, và nó sẽ chỉ tạo ra một sự kiện click cho toàn bộ danh sách, nhưng sau đó tôi wouldn không thể truy cập vào dữ liệu mô hình tương ứng với mục danh sách được nhấp.

Các nhà phát triển xương sống mô hình nào sử dụng để giải quyết vấn đề điển hình này?

Trả lời

2

Bạn có thể kết hợp các trường hợp với một yếu tố như vậy:

events : { 
    'click li' : 'log' 
}, 

log: function(e) { 
var elm = e.currentTarget //Same as `this` in normally bound jQuery event 


jQuery.data(elm, "viewInstance").log(e); 
}, 

Sau đó:

var ListItemView = Backbone.View.extend() { 

    tagName: 'li', 

    log : function() { 
    console.log(this.model.get("title"); 
    } 

    render: function() { 
     //Associate the element with the instance 
    $(this.el).html(this.template(this.model.toJSON())).data("viewInstance", this); 
    return this; 
    } 
}); 
+1

Cảm ơn câu trả lời của bạn. Đây là những gì tôi đã phải làm để giải quyết vấn đề này cho đến bây giờ, nhưng sau đó một lần nữa, Nó đang sử dụng jQuery để lưu trữ dữ liệu trong DOM, không cảm thấy như một cách tiếp cận rất sạch sẽ trong thời gian dài. – Daniel

+1

@ Daniel Vâng jQuery không lưu trữ dữ liệu trong DOM, nó lưu trữ nó trong một đối tượng js thông thường ('jQuery.cache'). jQuery cũng gây ô nhiễm nội bộ bất kỳ phần tử nào có (các) sự kiện với thuộc tính expando, sau đó thực hiện 'dữ liệu' trên phần tử không có tác dụng ngoài việc thêm các thuộc tính khác trong đối tượng js thông thường. – Esailija

+0

Ah Ok. tôi đoán điều đó sẽ xảy ra sau đó. cảm ơn – Daniel

3

Theo dõi các bản xem trước từ chế độ xem gốc. Sau đó, khi thêm subview thêm nó vào băm cũng như thêm cid vào el của subview. Bằng cách này có một con trỏ đến subview và có thể thực hiện các hoạt động trên mô hình của nó ...

Tôi đã không kiểm tra mã chính xác dưới đây để điều này có thể sai ở một hoặc hai chỗ nhưng tôi đã thử nghiệm nguyên tắc chung này. Tôi cũng đã bỏ qua mã listitemview.

var ListView = Backbone.View.extend() { 
    subViews: {}, 
    tagName: 'ul', 
    events: { 
    'click li' : 'clickItem' 
    }, 
    clickItem: function(event){ 
    var id = event.currentTarget.cid; 
    var subView = this.subViews[id]; 


    }, 
    render: function() { 

    this.collection.each(function(item) { 
     var view = new ListItemView({model: item}); 
     this.subViews[view.cid] = view; 
     subEl = view.render().el; 
     subEl.cid = view.cid; 
     $(this.el).append(subEl); 
    }); 
    return this; 
    } 
}); 
Các vấn đề liên quan