2012-06-06 37 views
25

tôi có thể đính kèm xử lý để Backbone xem như:Làm cách nào để đính kèm 2 trình xử lý vào cùng một sự kiện?

var TodoView = Backbone.View.extend({ 
    events: { 
     "xxx": "eventHandler1" 
     "yyy": "eventHandler2" 
    } 
}); 

Nhưng nếu tôi muốn đính kèm nhiều hơn 1 handler cho sự kiện giống nhau không?

var TodoView = Backbone.View.extend({ 
    events: { 
     "xxx": "eventHandler1" 
     "yyy": "eventHandler2" 
     "xxx": "eventHandler3" // this isn't valid ... at least in CoffeeScript 
    } 
}); 

tôi có thể tạo ra một handler tùy chỉnh như

Nhưng điều này dường như không lý tưởng ...

+0

Tôi sẵn sàng đặt cược "xxx": "eventHandler1 eventHandler2" hoạt động, thử nghiệm ngay –

+1

@AndyRay: Bạn muốn đặt cược bao nhiêu? https://github.com/documentcloud/backbone/blob/master/backbone.js#L1242 –

+0

@muistooshort, vì vậy tôi có thể nói phương pháp tôi nên sử dụng bây giờ là: '" eventname ": function (e) {handler1 (e); handler2 (e)} '? – jm2

Trả lời

36

này:

events: { 
    "xxx": "eventHandler1", 
    "yyy": "eventHandler2", 
    "xxx": "eventHandler3" 
} 

sẽ không làm việc vì events là một đối tượng theo nghĩa đen và bạn có thể có nhiều nhất một cặp (khóa, giá trị) trong một đối tượng. Đó có lẽ sẽ là giống như nói:

events: { 
    "xxx": "eventHandler3", 
    "yyy": "eventHandler2" 
} 

CoffeeScript này:

events: 
    "xxx": "eventHandler1" 
    "yyy": "eventHandler2" 
    "xxx": "eventHandler3" 

là chức năng giống hệt với phiên bản JavaScript và sẽ không làm việc vì lý do tương tự. Ý tưởng của việc sử dụng

Andy Ray

'event selector': 'callback1 callback2'` 

sẽ không hoạt động hoặc là Backbone sẽ không hiểu rằng nó nên chia giá trị trên khoảng trắng; tương tự, điều này:

'event selector': [ 'callback1', 'callback2' ] 

sẽ không hoạt động vì Backbone không biết phải làm gì với một mảng trong ngữ cảnh này.

xem liên kết các sự kiện của họ thông qua delegateEvents và trông như thế này:

delegateEvents: function(events) { 
    // Some preamble that doesn't concern us here... 
    for (var key in events) { 
    var method = events[key]; 
    if (!_.isFunction(method)) method = this[events[key]]; 
    if (!method) throw new Error('Method "' + events[key] + '" does not exist'); 
    // And some binding details that are of no concern either... 
    } 
} 

Vì vậy method bắt đầu ra làm giá trị cho 'event selector'.Nếu nó là một chức năng từ một cái gì đó như:

'event selector': function() { ... } 

sau đó nó được sử dụng như nó vốn có, nếu không nó được chuyển thành tài sản của this:

method = this[events[key]]; // i.e. method = this[method] 

Nếu một người dũng cảm, người ta có thể điều chỉnh delegateEvents để hiểu chuỗi ký tự phân cách hoặc khoảng trắng:

// Untested code. 
var methods = [ ]; 
if (_.isArray(method)) 
    methods = method; 
else if (_.isFunction(method)) 
    methods = [ method ]; 
else 
    methods = method.split(/\s+/); 
for (var i = 0; i < methods.length; ++i) { 
    method = methods[i]; 
    if (!_.isFunction(method)) 
    method = this[method]; 
    // And the rest of the binding stuff as it is now with a possible adjustment 
    // to the "method does not exist" exception message... 
} 

Một bản vá khá đơn giản như thế sẽ cho phép bạn sử dụng danh sách xử lý được phân cách bằng khoảng trắng:

'event selector': 'callback1 callback2' 

hoặc một mảng của bộ xử lý:

'event selector': [ 'callback1', 'callback2' ] 

hoặc thậm chí là một mảng hỗn hợp của tên phương pháp và chức năng:

'event selector': [ 'callback_name1', function() { ... }, 'callback_name2' ] 

Nếu bạn không muốn vá Backbone của bạn hoặc chuyển tiếp một bản vá như vậy cho những người bảo trì Backbone sau đó bạn có thể đi với ý tưởng "gửi đi thủ công" ban đầu của mình:

'event selector': 'dispatcher' 
//... 
dispatcher: function(ev) { 
    this.handler1(ev); 
    this.handler2(ev); 
} 
+0

+1 câu trả lời hay, kỹ lưỡng –

9

tôi giải quyết vấn đề này bằng cách sử dụng jQuery's event namespaces

var TodoView = Backbone.View.extend({ 
    events: { 
     "xxx.handler1": "eventHandler1", 
     "yyy": "eventHandler2", 
     "xxx.handler3": "eventHandler3" 
    } 
}); 

Đây không phải là những gì không gian tên sự kiện ban đầu được dành cho, nhưng miễn là họ không xung đột với không gian tên khác, nó không nên gây ra một vấn đề.

Vấn đề chính chỉ là bạn chỉ có thể có một giá trị cho mỗi khóa trong một đối tượng và điều này làm cho các phím duy nhất.

+0

Một câu trả lời hay. Tôi đã làm điều này: 'sự kiện: { 'nhấp vào.đầu tiên': 'hideAll', 'click.second a': 'showContent' }' – eightyfive

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