รับค่าก่อนหน้าของค่าที่สังเกตได้ในการสมัครรับข้อมูลที่สังเกตได้เดียวกัน


86

เป็นไปได้หรือไม่ที่จะได้รับค่าปัจจุบันของค่าที่สังเกตได้ภายในการสมัครรับข้อมูลที่สังเกตได้ก่อนที่จะได้รับค่าใหม่

ตัวอย่าง:

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
});

คำตอบ:


88

มีวิธีในการสมัครสมาชิกค่า before ดังนี้:

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");

สิ่งที่ไม่thisย่อมาจากที่นี่?
Thanasis Ioannidis

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

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

ใช้ด้านบนดังนี้:

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

});

2
ค่อนข้างใหม่สำหรับสิ่งที่น่าพิศวง แต่ฉันหวังว่านี่เป็นวิธีการตั้งค่าการสมัครสมาชิกเริ่มต้น หรือ .. อย่างน้อย fn นี้จะทำให้คันแรกของฉันหายไปเมื่อฉันใช้ 'สมัครสมาชิก' เป็นครั้งแรก
bkwdesign

1
มีการเคลื่อนไหวบางอย่างเกี่ยวกับเรื่องนี้เมื่อวันที่github.com/knockout/knockout/issues/914 ดูเหมือนว่าจะมีกำหนดสำหรับรุ่น 3.4
AlignedDev

2
ในกรณีที่ประเภทค่าที่สังเกตได้ที่สมัครเป็น Array คุณต้องแบ่งมันออกมิฉะนั้น oldValue จะเหมือนกับค่า newValue เสมอ ตรวจสอบตัวอย่างการทำงานที่นี่: jsfiddle.net/david_freire/xmk6u9yn/4
David Freire

1
เย็น. เพิ่มค่าส่งคืนซึ่งเป็นอ็อบเจ็กต์การสมัครสมาชิกด้วยdispose()ฟังก์ชันgist.github.com/30ff1f5c1adf215179b0046515f86e45
Michael

โอ้เพิ่งเห็นการสนทนา git
Michael

21

เปลี่ยนคำตอบ Beagle90 เล็กน้อย ส่งคืนการสมัครสมาชิกทุกครั้งเพื่อให้สามารถเข้าถึงตัวอย่างเช่น dispose ()

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;
};

2
นี่เป็นขั้นตอนที่แท้จริง แต่การเรียกร้อง.disposeค่าตอบแทนจากสิ่งนี้จะกำจัดการสมัครสมาชิกครั้งที่สองเท่านั้นไม่ใช่การ'beforeChange'สมัครสมาชิก
TRManderson

18

คำขอดึงจะเพิ่มคุณลักษณะนี้มีรหัสที่แตกต่างกันบางอย่างที่ลมขึ้นเป็นดีกว่าอาศัยโดยใช้beforeChangeเหตุการณ์

เครดิตทั้งหมดสำหรับการแก้ปัญหาของ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);
    });
};

อ้างไมเคิล:

เดิมทีฉันแนะนำให้ใช้beforeChangeเพื่อแก้ปัญหานี้ แต่ตั้งแต่นั้นมาก็ตระหนักว่ามันไม่น่าเชื่อถือเสมอไป (เช่นหากคุณเรียกvalueHasMutated()สิ่งที่สังเกตได้)


3

ฉันพบว่าฉันสามารถเรียก peek () จากค่าที่สังเกตได้จากการคำนวณที่เขียนได้เพื่อรับค่า before

สิ่งนี้ (ดู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
วิธีนี้ใช้ไม่ได้ผลเนื่องจากเมื่อมีการเรียกใช้การโทรกลับของการสมัครรับข้อมูลค่าก็เปลี่ยนไปแล้วและpeek()จะให้ค่าใหม่แก่คุณ
Michael Teper

@MichaelTeper ฉันรู้ว่าฉันโพสต์คำตอบของฉันเมื่อปีที่แล้ว แต่หลังจากที่ฉันได้รับการโหวตลดลงฉันเพิ่งทดสอบและมันใช้งานได้ ดู: jsfiddle.net/4MUWp
rjmunro

ตกลงฉันเห็นสิ่งที่คุณทำที่นั่น ... คำถามเกี่ยวกับการดึงค่าในการsubscribeเรียกกลับซึ่งไม่สามารถทำได้ด้วย peek () ตัวอย่างของคุณไม่ได้พิสูจน์อะไรและอาจทำให้ผู้มาใหม่สับสน โดยพื้นฐานแล้วคุณกำลังตัดตัวแปรส่วนตัวที่นี่และแสดงค่าก่อนที่จะตั้งค่า - แน่นอนว่ามันจะไม่มีการเปลี่ยนแปลง
Simon_Weaver
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.