2017-12-27 7 views
1

Betrachten Sie den folgenden Code ein:Schreiben C# -ähnliche Erweiterungen in JavaScript für Knockout beobachtbare

if (countriesLookup()) { 
    countriesLookup().fill(initialData.Countries); 
} else { 
    const subscription = countriesLookup.subscribe(function (lookup) { 
     lookup.fill(initialData.Countries); 
     subscription.dispose(); 
    }); 
} 

Hier habe ich eine ko.observable countriesLookup haben. Wenn zum Zeitpunkt der Dateninitialisierung die Komponente selbst noch nicht initialisiert ist (countriesLookup() == undefined), abonniere ich diese Observable, und wenn sie schließlich die Komponente erhält, führe ich die Initialisierung mit den Anfangsdaten durch und werde das Abonnement los.

Lassen Sie uns für den Moment vergessen, dass dieser Ansatz zu Callback-Hölle etc. führt, und überlegen Sie, wie Sie dies weniger hässlich machen können.

Ich wollte so etwas wie C# Erweiterungen beobachtbar schreiben, wie die in Gebrauch sein würde:

countriesLookup.initialize(x => x.fill(initialData.Countries)); 

Und die Umsetzung setzt so aussehen:

ko.observable.prototype.initialize = function(initializeFunc) { 
    const currentValue = ??? 
    if (currentValue()) { 
     initializeFunc(currentValue()); 
    } else { 
     const subscription = currentValue.subscribe(function (lookup) { 
      initializeFunc(lookup); 
      subscription.dispose(); 
     }); 
    } 
} 

Offensichtlich, das nicht der Fall ist Arbeit, vor allem, weil ich nicht sicher bin, ob es möglich ist, den aktuellen Wert von Observable innerhalb der "Extension" -Methode zu erhalten.

Ich denke derzeit in Bezug auf C# -Programmierung, wo ich etwas kompetent bin, und möchte sehr viel Ratschläge, wie ich eine solche Erweiterung schreiben sollte.


Vielleicht sollte ich meine Probleme ein wenig mehr erklären. Ich bin mir bewusst, dass der aktuelle Wert mit this innerhalb der Methode zum Prototyp hinzugefügt werden konnte, aber das Problem liegt in der Tatsache, dass Observable eine Funktion zurückgibt.

Zum Beispiel dieses

String.prototype.SayHi = function SayHi() { 
    return "Hi " + this + "!"; 
}; 
"blah".SayHi();  //return "Hi blah!" 

funktioniert gut, aber die

ko.observable.prototype.SayHi = function SayHi() { 
    return "Hi " + this + "!"; 
}; 
var a = ko.observable("blah") 
a.SayHi(); 

schlägt mit dem folgenden Fehler:

VM543:1 Uncaught TypeError: a.SayHi is not a function at <anonymous>:1:3

Ich hoffe, dass es eine Klarstellung gegeben.

Antwort

2

Wenn ich Ihren Punkt verstehe, ist es Ihr Ziel, eine benutzerdefinierte Funktion für die Observablen hinzuzufügen.
In diesem Fall sollten Sie fn anstelle von verwenden.
Überprüfen Sie diesen Link aus: http://knockoutjs.com/documentation/fn.html

I am not sure if this is possible to get the current value of observable inside the "extension" method

Und Sie können den aktuellen Wert Ihrer beobachtbaren mit dieser Methode, so dass Sie Ihre obigen Beispiel ist ganz in der Nähe zu dem, was Sie wollen.

ko.observable.fn.initialize = function(initializeFunc) { 
 
    const currentValue = this; 
 
    if (currentValue()) { 
 
    initializeFunc(currentValue()); 
 
    } else { 
 
    const subscription = currentValue.subscribe(function(lookup) { 
 
     initializeFunc(lookup); 
 
     subscription.dispose(); 
 
    }); 
 
    } 
 
    return this; 
 
} 
 

 
var ViewModel = function() { 
 
    this.data = ko.observable().initialize(x => console.log("Value changed to: " + x)); 
 
    this.data("100"); 
 
}; 
 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

================================
HINWEIS: Es gibt eine Diskussion darüber, warum fn anstelle von verwendet wird und jemand darauf hingewiesen, dass es besser ist, extenders aus Gründen der Leistung zu verwenden.
Lesen Sie hier: https://github.com/knockout/knockout/issues/979

+0

Toller Job, Adrian! Vielen Dank! –

+0

Gern geschehen! – Adrian

Verwandte Themen