2011-12-13 27 views
5

Sử dụng backbone.js ...Sự kiện thay đổi của mô hình sẽ không kích hoạt khi cập nhật mảng?

@model.bind 'change',()-> console.log 'updated' 

addIndex = (index) => 
    array = @model.get('array') 
    array.push index 
    @model.set 
     array: array 

này cập nhật mô hình hoàn hảo nhưng không kích hoạt sự kiện thay đổi. Có ai biết tại sao không nhìn vào những gì tôi đăng?

EDIT:

tôi thêm này và nó gây nên sự kiện thay đổi:

@model.set 
    test: '' 

num = 0 
setInterval()=> 
    num++ 
    @model.set 
    test: num 
, 3000 

tôi thêm này và nó không gây ra sự kiện thay đổi:

@model.set 
    test: [] 

num = 0 
setInterval()=> 
    console.log 'testupdate' 
    num++ 
    test = @model.get('test') 
    test.push num 
    @model.set 
     test: test 
, 3000 
+0

là mảng nhận được dân cư? – Brian

+0

Yea mô hình cập nhật tốt và mảng được điền chính xác trong các thuộc tính mô hình. – fancy

Trả lời

6

Vấn đề là bạn đang đặt giá trị với giá trị hiện tại. Hãy nhìn vào mã nguồn:

http://documentcloud.github.com/backbone/docs/backbone.html#section-33

Khi bạn gọi set nó có một điều khoản bảo vệ để đảm bảo rằng bạn không thiết lập các giá trị như nhau (để tránh các vòng lặp sự kiện). Trong trường hợp của bạn, bạn đang nhận được mảng, sửa đổi nó, và thiết lập nó một lần nữa, mà sẽ không kích hoạt sự kiện của bạn.

Tất nhiên, khi bạn set test: {}, nó là một mục mới có đối tượng mới, vì vậy nó sẽ kích hoạt lại. Nếu bạn thực sự muốn kích hoạt sự kiện, bạn có thể đặt nó thành null, sau đó đặt nó thành một mảng trống và sau đó nhập vào mảng được điền lại ...

8

Câu trả lời của Brian là lý do thật tuyệt vời!

Muốn trình bày một cách khác để có được những gì bạn muốn thay vì vô hiệu hóa nó hoặc nhân bản mảng.

Chỉ cần tự kích hoạt sự thay đổi bản thân:

addIndex = (index) => 
    array = @model.get('array') 
    array.push index 
    @model.trigger('change:array',@model, array) 
+0

Nếu bạn có một mảng nhân bản đặc biệt lớn thì đó là một lựa chọn tồi.Điều này có ý nghĩa hơn. –

+0

Với giải pháp này model.changed sẽ không được cập nhật. – postnerd

1

bạn có thể xem xét sử dụng một bộ sưu tập Backbone thay vì một mảng, và sau đó ràng buộc để thay đổi các sự kiện trong bộ sưu tập đó?

7

Vì bạn đang đặt đối tượng được tham chiếu, hãy sử dụng _.clone().

test = _.clone @model.get('test') 
test.push num 
@model.set test: test 

Vì bạn không còn sử dụng đối tượng/mảng được tham chiếu để đặt chính nó, nó sẽ kích hoạt sự kiện thay đổi nếu sự kiện đã thay đổi.

6

Cách khác, khi thay đổi đối tượng hoặc mảng, là âm thầm hủy đặt thuộc tính trước khi đặt giá trị cập nhật mới. Một cái gì đó như thế này:

(function() { 
    var arr, model = new Model(); 

    model.set("arrayProp", [1, 2, 3]); 
    arr = model.get("arrayProp"); 
    arr.push(4); 

    model.unset("arrayProp", { silent: true }); 
    model.set("arrayProp", arr); 
})(); 

Bằng cách đặt silent: true khi unset các prop, sự kiện thay đổi sẽ chỉ bắn một lần (Khi phương pháp set() được gọi và tài sản đã được cập nhật).

Không có sự khác biệt nào giữa việc thực hiện việc này hoặc gọi thủ công sự kiện, đó chỉ là vấn đề sở thích cá nhân.

+2

Tôi thích tùy chọn này - theo cách này, Backbone kích hoạt tất cả các biến thể sự kiện ('change' và' change: arrayProp') với các tham số mặc định, vì vậy nó sẽ không phá vỡ bất kỳ người nghe nào. – joews

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