2013-01-25 38 views
21

Tôi backbone.js học, và cảm thấy bối rối về điều này: tôi đang theo hướng dẫn: http://arturadib.com/hello-backbonejs/Khi nào tôi cần sử dụng _.bindAll() trong Backbone.js?

như bạn có thể thấy trong ví dụ đầu tiên (1.js):

(function($){ 
    var ListView = Backbone.View.extend({  
    el: $('body'), // attaches `this.el` to an existing element. 

    initialize: function(){ 
     _.bindAll(this, 'render'); // fixes loss of context for 'this' within methods 

     this.render(); // not all views are self-rendering. This one is. 
    }, 

    render: function(){ 
     $(this.el).append("<ul> <li>hello world</li> </ul>"); 
    } 
    }); 

    var listView = new ListView();  
})(jQuery); 

Nhưng nếu tôi nhận xét câu: _.bindAll(this, 'render');, điều này sẽ vẫn hoạt động. Tôi đã tìm kiếm trong google và ai đó nói rằng phương pháp bindAll() là cần thiết vì nếu tôi đã chuyển ngữ cảnh của mình, việc gọi số this.render có thể không khả dụng. Tôi cảm thấy bối rối về "ngữ cảnh". và cũng có thể một số người có thể giải thích cho tôi khi gọi (this.render) sẽ không có sẵn?

Trả lời

26

Ví dụ bạn đã cho _.bindAll(this, 'render'); là không cần thiết nhưng nếu bạn có chức năng gọi lại trong đó this có thể được thay đổi thành ngữ cảnh khác, thì _bindAll() có thể hữu ích.

Ví dụ:

initialize: function(){ 
    _.bindAll(this, 'render', 'clickFunc'); 
}, 
events: { 
    'click .someElement': 'clickFunc' 
}, 
clickFunc: function(e) { 
    /** If you remove the clickFunc from the list of events in bindAll, 
      'this' will refer to the element that invoked the event. 

     Adding the clickFunc event in the _.bindAll, ensures that 'this' stays 
      as the view. 
    */ 
    this /** <-- our focal point */ 
} 
+9

bất cứ điều gì trong các sự kiện đã bị ràng buộc tự động bởi xương sống, FYI. –

+0

giải thích rất hay, công việc tuyệt vời – M3ghana

2

trong trường hợp này bạn không cần _.bindAll, nhưng chúng ta hãy nói xem bạn có một phương pháp mà gây ra một rerender và bạn làm điều gì đó như thế này:

.., 
myMethod: function() { 
    this.$('.someselector').change(this.render); 
}, 

nếu bạn không có _.bindAll cho render , bối cảnh của bạn sẽ bị tắt.

10
  • Bất kỳ phương pháp liệt kê như giá trị tài sản trong các sự kiện của quan điểm của bạn băm sẽ được tự động bị ràng buộc cho bạn bằng cách xương sống
  • Bất kỳ phương pháp theo quan điểm của bạn mà bạn tự sử dụng như xử lý sự kiện từ các mô hình hoặc bộ sưu tập nên bị trói buộc bằng tay qua bindAll
    • HOẶC bạn có thể cung cấp một bối cảnh khi bạn đăng ký các ràng buộc
    • HOẶC bạn có thể sử dụng emca 5 của function.bind để có được kết quả tương tự

đoạn:

events: { 
    'click .win': 'win', 
    'click .lose': 'lose' 
}, 
initialize: function() { 
    //win and lose are automatically bound for you 
    //because they are in the events property 

    //refresh must be manually bound 
    this.model.on('change', this.refresh); 

    //which you can do ECMA5 style if you like 
    this.model.on('change', this.refresh.bind(this)); 

    //OR you can provide a context backbone style 
    this.model.on('change:foo', this.fooChange, this); 

    //However, since you pretty much never want an unbound function 
    //in a view, you can just stick this in all your initialize methods 
    //and call it done 
    //Note this will bind all functions in your view class if you don't 
    //pass specific method names. I recommend this form. 
    _.bindAll(this); 
}, 
win: function() {...}, 
lose: function() {...}, 
refresh: function() {...}, 
fooChange: function() {...} 

... OOOOORRRR chỉ cần sử dụng CoffeeScript và mũi tên chất béo và giải quyết việc này sạch ở cấp ngôn ngữ.

+2

Tôi thích nhiều hơn _.bindAll (điều này) cũng vậy, nhưng gạch dưới không khuyên bạn nên nó, và nó sẽ không được hỗ trợ nữa kể từ phiên bản 1.5.0. Trong danh sách thay đổi bạn có thể đọc: Đã xóa khả năng gọi _.bindAll không có đối số tên phương thức. Nó luôn luôn khá khôn ngoan hơn khi liệt kê tên của các phương pháp mà bạn muốn ràng buộc. http://underscorejs.org/#changelog Tôi nghĩ rằng đó là một lỗi. Tôi sẽ khó khăn hơn nhiều để duy trì. – ccsakuweb

+0

@ccsakuweb Tôi hiện đang làm việc trên một giao diện web nơi tôi sử dụng rất nhiều Backbone. Trong dự án này, tôi hiện có chính xác * một * gọi đến '_.bindAll', và không có gì để' _.bind'. Thay vào đó, tôi sử dụng 'this.listenTo' để nghe các sự kiện mô hình, hàm băm' sự kiện' cho các sự kiện DOM, vv và cung cấp ngữ cảnh theo cách đó. Lệnh gọi '_.bindAll' là cho phương thức' run' của background autorefresher, gọi 'setTimeout (this.run, period)' làm cho phương thức 'run' mất ngữ cảnh của nó. Mọi thứ khác đến thời điểm này đã được quản lý một cách hoàn hảo mà không có '_.bindAll'. –

2

Cho phép có một cái nhìn cận cảnh những gì _.bindAll làm từ underscore.js offical docs.

_.bindAll = function(obj) { 
    var i, length = arguments.length, key; 
    if (length <= 1) throw new Error('bindAll must be passed function names'); 
    for (i = 1; i < length; i++) { 
     key = arguments[i]; 
     obj[key] = _.bind(obj[key], obj); 
    } 
    return obj; 
    }; 

Điều cần làm là tự động ràng buộc tất cả các chức năng của nó với ngữ cảnh chính xác. (theo đó chức năng của nó được khai báo thay vì được gọi ra

Cá nhân tôi nghĩ đó là quy ước cho phiên bản cũ của Backbone.js để ràng buộc events hoặc trình nghe hành động DOM của nó. .Tìm kiếm thêm bằng cách tìm kiếm Binding "this"here

Tôi hy vọng điều đó sẽ hữu ích.

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