2012-06-06 21 views
5

Điều này có vẻ ngớ ngẩn, nhưng trong ngày và tuổi tác, người ta có thể mong đợi JS nâng cao một sự kiện nếu nội dung của một mảng đã thay đổi.Có cách nào để nhận lại cuộc gọi khi giá trị mục mảng đã thay đổi không?

Một số câu hỏi đã được hỏi về việc được thông báo khi một thay đổi biến thay đổi (xác định getter hoặc setter). Và có vẻ là a way to do that (ít nhất là đối với hầu hết các trình duyệt kể cả IE6 +)

Vấn đề của tôi là tôi đang cố gắng để có được thông báo nếu một mục bên trong một sự thay đổi mảng:

var ar = ["one", "two", "three"]; 
    // setting the whole array will call the custom setter method 
    // (assuming you defined it) 

    ar = ["one", "three", "five"]; 

    // however, this will only call the getter method and won't call the setter 
    // without defining custom setters for every item in the array. 

    ar[1] = "two"; 

Rõ ràng, tôi cố gắng tránh sử dụng trình mã hóa để sử dụng các hàm .getVale() và .setValue() kiểu cũ của trường java để truy cập/sửa đổi dữ liệu.

+0

Backbone.js có thể kích hoạt các sự kiện khi mô hình bộ sưu tập thay đổi. Không hoàn toàn giống nhau, nhưng bạn có thể thấy cách họ làm điều đó. – asawyer

+1

Bạn có thể có mảng như một biến riêng của một đối tượng, thì cách duy nhất để thay đổi biến là sử dụng một phương thức trên đối tượng đó, có thể kích hoạt sự kiện ... –

+1

Tôi nghĩ bạn nên đọc về [mẫu có thể quan sát] (http://jsclass.jcoglan.com/observable.html) – MilkyWayJoe

Trả lời

0

Ok, dựa trên mã @ David Wolever và ý kiến ​​khác, có thực sự là một giải pháp:

Sử dụng các ghi chú từ John Dyer để thực hiện các phương pháp addProperty. Đặt một setTimeout trong phương thức getter để so sánh với giá trị ban đầu trong một thời gian ngắn sau khi đọc diễn ra:

addProperty(myObject, 'vals', 
    function() { 
     var _oldVal = "" + this._val; 
     var _parent = this; 
     console.log('getter!'); 
     setTimeout(function() { 
      var curVal = "" + _parent._val; 
      if (curVal != _oldVal) 
       console.log('array changed!'); 
     }, 200); 
     return this._val; 
    }, 
    function (value) { 
     console.log('setter!'); 
     this._val = value; 
    }); 

    myObject.vals = ["one", "two", "three"]; 
    myObject.vals[1] = "five"; 
3

Tóm lại: không, bạn không thể. Bạn sẽ nhận thấy rằng Arrays không cung cấp bất kỳ cơ chế điều phối sự kiện nào và API của chúng không bao gồm bất kỳ chức năng kiểu gọi lại nào.

Trong dài hơn: như những người khác đã lưu ý, nó có thể quấn mảng ... Và nó cũng có thể thăm dò ý kiến ​​các mảng nội dung:

function watchArray(arr, callback) { 
    var oldVal = "" + arr; 
    setInterval(function() { 
     var curVal = "" + arr; 
     if (curVal != oldVal) { 
      callback(); 
      oldVal = curVal; 
     } 
    }, 100); 
} 

Nhưng phương pháp này có một số vấn đề rõ ràng: nó cuộc thăm dò, nó' ll được chậm để xem một loạt các mảng vv

+0

Cảm ơn bài đăng này. Vì getter không được gọi khi một phần tử mảng được thay đổi, và của bạn là một cách để so sánh => getter + delay + comapre = thay đổi thông báo. Vấn đề chậm là tìm ra yếu tố nào đã thay đổi (ít vấn đề hơn đối với tôi). – MandoMando

+1

Phương pháp defineProperty mới được đề xuất bởi @Phrogz ở trên là gì? –

0

Tôi nghĩ timeout giải pháp dựa trên không phải là tốt nhất.
Nếu bạn chỉ có thể sử dụng push và pop để sửa đổi mảng, bạn có thể ghi đè lên pushpop phương pháp Array nguyên mẫu (hoặc chỉ có một số đối tượng mà bạn muốn theo dõi):

var myWatchableArr = []; 
myWatchableArr.setChangeCallback = function(callback){ 
    this.changeCallback = callback; 
} 
myWatchableArr.push = function(e){ 
    Array.prototype.push.call(this,e); 
    if(typeof this.changeCallback == "function") 
     this.changeCallback(this); 
} 
myWatchableArr.push(3); 
myWatchableArr.setChangeCallback(function(arr){ 
    console.log("the array has been changed", arr); 
}); 
// now watching for changes 
myWatchableArr.push(4); 

Nếu push và pop không đủ, bạn có thể thêm một số phương pháp setAt để sử dụng như myWatchableArr.setAt(3, value) thay vì myWatchableArr[3]=value.

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