Kapan menggunakan ko.utils.unwrapObservable?

114

Saya telah menulis beberapa binding kustom menggunakan KnockoutJS. Saya masih tidak yakin kapan harus menggunakan ko.utils.unwrapObservable(item)Melihat kode, panggilan itu pada dasarnya memeriksa untuk melihat apakah itemdapat diamati. Jika ya, kembalikan nilai (), jika tidak, kembalikan nilainya. Melihat bagian di Knockout tentang membuat binding kustom, mereka memiliki sintaks berikut:

var value = valueAccessor(), allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);

Dalam hal ini, mereka memanggil yang dapat diamati melalui ()tetapi kemudian juga memanggil ko.utils.unwrapObservable. Saya hanya mencoba untuk mengetahui kapan harus menggunakan satu vs. yang lain atau jika saya harus selalu mengikuti pola di atas dan menggunakan keduanya.

arb
sumber

Jawaban:

142

Anda harus menggunakan ko.utils.unwrapObservabledalam kasus di mana Anda tidak tahu apakah Anda telah diberi pengamatan atau tidak. Ini biasanya akan berada dalam pengikatan khusus di mana yang dapat diamati atau yang tidak dapat diamati dapat terikat padanya.

Dalam kode yang Anda miliki di atas, panggilan ke valueAccessor()sebenarnya tidak membuka bungkusan yang dapat diamati. Ini hanya mengambil nilai yang diteruskan ke pengikatan dalam konteks yang benar (ini dibungkus dalam fungsi untuk melindunginya). Nilai pengembalian valueAccessor()mungkin dapat diamati atau tidak. Itu adalah apa pun yang diteruskan ke pengikatan.

RP Niemeyer
sumber
4
Itu sangat tergantung pada situasinya. Beberapa binding kustom dirancang untuk hanya berfungsi dengan observable, jadi Anda dapat memeriksa di depan (ko.isObservable) bahwa binding tersebut dapat diobservasi dan kemudian Anda bebas untuk membukanya dengan (). Jika Anda menerima objek yang mungkin memiliki observable bertingkat, maka Anda lebih baik melakukan ko.toJS(yourObject)daripada menggunakan ko.utils.unwrapObservable, jika Anda mencoba untuk mendapatkan versi yang tidak terbungkus dari objek untuk diteruskan ke widget atau pustaka pihak ketiga. Secara umum, ini paling aman digunakan ko.utils.unwrapObservableuntuk mendukung yang dapat diamati dan yang tidak dapat diamati.
RP Niemeyer
2
Saya kira saya bingung dengan apa tujuannya ko.utils.unwrapObservable. Melihat kodenya, itu hanya memeriksa untuk melihat apakah itu dapat diamati dan jika ya, Knockout memanggil ()untuk mendapatkan nilai yang dapat diamati, jika tidak, itu hanya mengembalikan nilai untuk yang tidak dapat diamati. Jika yang saya minati hanyalah nilai data yang diteruskan ke pengikatan, mengapa saya tidak bisa selalu menggunakan ()?
arb
17
Anda tidak tahu apakah Anda lolos observable atau non-observable dalam binding. Katakanlah saya punya myBindingdan seseorang mengikat seperti data-bind="myBinding: myValue". myValuemungkin dapat diamati atau mungkin hanya properti biasa pada model tampilan. Jika ini hanya properti dan saya menyebutnya seperti fungsi, maka Anda akan mendapatkan error. ko.utils.unwrapObservableakan dengan aman mengembalikan nilai kepada Anda terlepas dari apakah Anda lulus pengamatan atau tidak.
RP Niemeyer
10
Saya juga merekomendasikan penggunaan singkatan 'ko.unwrap' karena 'ko.utils.unwrapObservable' adalah ekspresi yang sangat panjang.
Ivan Nikitin
3
@IvanNikitin - tentu saja, hanya ingin menunjukkan bahwa ko.unwraptersedia dalam versi 3.0+. Jika Anda menggunakan lebih lama dari 3.0, maka ko.utils.unwrapObservablemasih ada.
RP Niemeyer
12

Jawaban sebelumnya benar, tetapi sering kali saya meneruskan fungsi ke pengikatan khusus (fungsi yang memeriksa izin, atau menentukan apa yang harus dilakukan berdasarkan hal lain, dll). Yang benar-benar saya butuhkan adalah membuka bungkus fungsi apa pun, meskipun itu bukan sebuah observasi.

Berikut ini secara rekursif membuka SEMUANYA:

ko.utils.unwrapFunction = function (func) {
    if (typeof func != 'function') {
        return func;
    }
    else {
        return ko.utils.unwrapFunction(func());
    }
};

Berikut adalah contoh penjilidan kustom sederhana yang saya tulis:

//replaces single and double 'smart' quotes users commonly paste in from word into textareas and textboxes with normal text equivalents
//USAGE:
//data-bind="replaceWordChars:true
//also works with valueUpdate:'keyup' if you want"

ko.bindingHandlers.replaceWordChars = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var bindingValue = ko.utils.unwrapFunction(valueAccessor);

        if (bindingValue) {
            $(element).val(removeMSWordChars(allBindingsAccessor().value())); //update DOM - not sure why I should need to do this, but just updating viewModel doesn't always update DOM correctly for me
            allBindingsAccessor().value($(element).val()); //update viewModel
        }
    }
}

Dengan cara ini bindingValue selalu berisi nilai. Saya tidak perlu khawatir tentang apakah saya meneruskan fungsi, yang dapat diamati, nilai, atau bahkan fungsi di dalam yang dapat diamati. Ini akan membuka semuanya dengan benar sampai mencapai objek yang saya inginkan.

Harapan yang membantu seseorang.

pilavdzice.dll
sumber