Nhận giá trị trước đó của một giá trị có thể quan sát được trong đăng ký của cùng một giá trị có thể quan sát được


85

Có thể loại trực tiếp để nhận được giá trị hiện tại của một giá trị có thể quan sát được trong một đăng ký cho có thể quan sát đó, trước khi nó nhận được giá trị mới không?

Thí dụ:

this.myObservable = ko.observable();
this.myObservable.subscribe(function(newValue){
    //I'd like to get the previous value of 'myObservable' here before it's set to newValue
});

Câu trả lời:


88

Có một cách để đăng ký giá trị trước như sau:

this.myObservable = ko.observable();
this.myObservable.subscribe(function(previousValue){
    //I'd like to get the previous value of 'myObservable' here before it's set to newValue
}, this, "beforeChange");

cái gì thisviết tắt ở đây?
Thanasis Ioannidis

151
ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

    this.subscribe(function (newValue) {
        callback(newValue, oldValue);
    });
};

Sử dụng ở trên như thế này:

MyViewModel.MyObservableProperty.subscribeChanged(function (newValue, oldValue) {

});

2
khá mới đối với loại trực tiếp, nhưng tôi ước đây là cách thiết lập đăng ký mặc định. Hoặc .. fn này ít nhất sẽ làm tôi ngứa đầu tiên khi tôi sử dụng 'đăng ký' lần đầu tiên.
bkwdesign

1
Đã có một số chuyển động về vấn đề này trên github.com/knockout/knockout/issues/914 . Có vẻ như nó được dự kiến ​​cho bản phát hành 3.4.
Căn chỉnh

2
Trong trường hợp loại giá trị có thể quan sát được đã đăng ký là Mảng, bạn phải cắt nó, nếu không oldValue sẽ luôn giống với newValue. Kiểm tra một ví dụ hoạt động, tại đây: jsfiddle.net/david_freire/xmk6u9yn/4
David Freire

1
Mát mẻ. Đã thêm giá trị trả về là một đối tượng đăng ký có dispose()hàm gist.github.com/30ff1f5c1adf215179b0046515f86e45
Michael

Oh chỉ nhìn thấy cuộc trò chuyện git.
Michael

21

Thay đổi nhỏ đối với câu trả lời Beagle90. Luôn trả lại chính đăng ký để có thể truy cập vào dispose () chẳng hạn.

ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

    var subscription = this.subscribe(function (newValue) {
        callback(newValue, oldValue);
    });

    // always return subscription
    return subscription;
};

1
Đây là một bước thực lên, nhưng gọi .disposevào giá trị trả về từ này sẽ chỉ dispose của thuê bao thứ hai, không phải là 'beforeChange'thuê bao
TRManderson

18

Các yêu cầu kéo thêm tính năng này có một số mã khác nhau mà gió lên là tốt hơn so với dựa vào việc sử dụng các beforeChangesự kiện.

Tất cả tín dụng cho giải pháp cho Michael Best

ko.subscribable.fn.subscribeChanged = function (callback) {
    var savedValue = this.peek();
    return this.subscribe(function (latestValue) {
        var oldValue = savedValue;
        savedValue = latestValue;
        callback(latestValue, oldValue);
    });
};

Để trích dẫn Michael:

Ban đầu tôi đề xuất sử dụng beforeChangeđể giải quyết vấn đề này nhưng sau đó nhận ra rằng nó không phải lúc nào cũng đáng tin cậy (ví dụ: nếu bạn gọi valueHasMutated()trên có thể quan sát).


3

Tôi nhận thấy rằng tôi có thể gọi peek () từ một giá trị quan sát được tính toán có thể ghi để nhận giá trị trước.

Một cái gì đó như thế này (xem http://jsfiddle.net/4MUWp ):

var enclosedObservable = ko.observable();
this.myObservable = ko.computed({
    read: enclosedObservable,
    write: function (newValue) {
        var oldValue = enclosedObservable.peek();
        alert(oldValue);
        enclosedObservable(newValue);
    }
});

1
Điều đó không hiệu quả, rất tiếc, vì vào thời điểm gọi lại đăng ký, giá trị đã thay đổi và do đó peek()sẽ cung cấp cho bạn giá trị mới.
Michael Teper

@MichaelTeper Tôi biết tôi đã đăng câu trả lời của mình một năm trước, nhưng sau khi nhận được một số phiếu phản đối, tôi vừa thử nghiệm nó và nó hoạt động. Xem: jsfiddle.net/4MUWp
rjmunro

Được rồi, tôi hiểu bạn đã làm gì ở đó ... Câu hỏi là về việc truy xuất giá trị trong một lệnh subscribegọi lại không thể thực hiện được với peek (). Ví dụ của bạn không chứng minh được gì và có thể gây nhầm lẫn cho người mới. Về cơ bản, bạn đang gói một biến private ở đây và hiển thị giá trị của nó trước khi đặt nó - vì vậy tất nhiên nó sẽ không thay đổi.
Simon_Weaver
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.