Kracht van een berekende eigendom functie uit te voeren

Gegeven een berekend eigendom

vm.checkedValueCount = ko.computed(function(){
  var observables = getCurrentValues();  //an array of ko.observable[]
  return _.filter(observables, function(v) { return v() }).length;
});

stel getCurrentValues() kan verschillende sets van het beperken van de zichtbaarheid die zijn gewijzigd elders in de code (en het komt uit een complexere structuur dan een observableArray).

Ik moet checkedValueCount te updaten wanneer

  • een van de afhankelijkheden veranderen
  • getCurrentValues() retourneert een andere set van het beperken van de zichtbaarheid.

Het probleem is dat ko.computed lijkt memoize de laatste geretourneerde waarde en worden alleen bijgewerkt wanneer een afhankelijkheid updates. Dit zorgt voor de eerste maar niet de laatste.

Wat ik zoek is een manier om de kracht checkedValueCount opnieuw uitvoeren. Iets wat ik kan gebruiken zoals:

changeCurrentValues();
vm.checkeValueCount.recalculate();

Zetten de meeste gewoon, ondanks dat ik

a = ko.computed(function() { return Math.random() })

hoe kan ik de kracht aanroepen a() keer terug te keren verschillende waarden.

  • Zie mijn bijgewerkt “herschreven” antwoord.

 

5 Replies
  1. 115

    Besefte ik dat mijn eerste antwoord gemist uw punt, en niet het oplossen van uw probleem.

    Het probleem is dat een berekende zal alleen opnieuw als er een waarneembaar die haar dwingt om opnieuw te evalueren. Er is geen standaard manier om de kracht van een berekende opnieuw te evalueren.

    Echter, je kunt deze met een aantal hacks door het maken van een dummy waarneembare waarde en vervolgens vertelde haar abonnees die het heeft gewijzigd.

    (function() {
    
        var vm = function() {
            var $this = this;
    
            $this.dummy = ko.observable();
    
            $this.curDate = ko.computed(function() {
                $this.dummy();
                return new Date();
            });
    
            $this.recalcCurDate = function() {
                $this.dummy.notifySubscribers();
            };        
        };
    
        ko.applyBindings(new vm());
    
    }());​

    Hier is een Viool waarop deze aanpak

    • Ah, ik heb dit geprobeerd maar ik moet hooked-up verkeerd. Dit ziet er hacky maar goede (en goed genoeg dat ik kan verlengen ko.berekend om het te laten werken
    • Zoals altijd het eenvoudiger is de beste.
    • Dit personeel wanneer u grote reeks van gegevens die niet waarneembaar en na veranderingen in een deel van de gegevens moet worden weergegeven.
    • Uw gebruik van notifySubscribers() is een goede. Beter dan wat ik aan het doen was van het bouwen van een willekeurig aantal en de instelling die de waarde van de dummy()
  2. 8

    Er is een methode te dwingen herberekening van al het beperken van de zichtbaarheid afhankelijk van jou:

    getCurrentValues.valueHasMutated()
    • Computeds niet over deze methode
    • getCurrentValues(); //an array of ko.observable[]
    • Oh ik zie het al. Je zegt het vinden van een waarneembare dat is een afhankelijkheid van de berekende en bel het valueHasMutated methode. Dit is niet echt fundamenteel verschillend van Josh ‘ s antwoord hierboven, is het? In feite dwingt je om te weten wat wordt verwezen en om te weten dat deze verwijzingen worden waargenomen (en niet berekend).
    • het is goed om te vermelden dat deze functie toch blijft een optie voor de lezers, maar misschien zou iemand de update geaccepteerd antwoord op te merken gevallen waarin deze functie kan worden uitgewisseld met notifySubscribers(), en als er enige boete of voordeel van beide manier.
  3. 4

    Dit antwoord is in principe hetzelfde als de ene @josh gaf, maar gepresenteerd als een meer generieke wrapper. Opmerking: deze versie is een ‘geschreven’ berekend.

    Ik ben met behulp van Getypte versie, dus ik heb begrepen van de ts.d eerste definitie. Dus negeer dit eerste deel als niet relevant voor u is.

    interface KnockoutStatic
    {
        notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
    }

    Kennisgeving-writeable berekend

    Een wrapper voor een beschrijfbare observable dat altijd oorzaken abonnees aangemeld te worden – zelfs als er geen beperking van de zichtbaarheid werden bijgewerkt als gevolg van de write call

    Vervang gewoon function<T> (options: KnockoutComputedDefine<T>, context) met function(options, context) als u geen gebruik van de Schrijfmachine.

    ko.notifyingWritableComputed = function<T> (options: KnockoutComputedDefine<T>, context)
    {
        var _notifyTrigger = ko.observable(0);
        var originalRead = options.read;
        var originalWrite = options.write;
    
        //intercept 'read' function provided in options
        options.read = () =>
        {
            //read the dummy observable, which if updated will 
            //force subscribers to receive the new value
            _notifyTrigger();   
            return originalRead();
        };
    
        //intercept 'write' function
        options.write = (v) =>
        {
            //run logic provided by user
            originalWrite(v);
    
            //force reevaluation of the notifyingWritableComputed
            //after we have called the original write logic
            _notifyTrigger(_notifyTrigger() + 1);
        };
    
        //just create computed as normal with all the standard parameters
        return ko.computed(options, context);
    }

    De belangrijkste use-case voor dit is wanneer u het bijwerken van iets dat anders niet zou leiden tot een verandering in een waarneembare die ‘bezocht’ door de read functie.

    Bijvoorbeeld, ik ben met behulp van LocalStorage om een aantal waarden, maar er is geen wijziging van enig waarneembaar te activeren re-evaluatie.

    hasUserClickedFooButton = ko.notifyingWritableComputed(
    {
        read: () => 
        {
            return LocalStorageHelper.getBoolValue('hasUserClickedFooButton');
        },
        write: (v) => 
        {
            LocalStorageHelper.setBoolValue('hasUserClickedFooButton', v);        
        }
    });

    Opmerking dat ik moest veranderen was ko.computed te ko.notifyingWritableComputed en dan is alles zorgt voor zichzelf.

    Als ik bel hasUserClickedFooButton(true) dan de ‘dummy’ waarneembaar is verhoogd dwingen alle abonnees (en hun abonnees) om de nieuwe waarde als de waarde in LocalStorage is bijgewerkt.

    (Opmerking: je kan denken dat het notify: 'always' extender is een optie, maar dat is iets anders).


    Er is een extra oplossing voor een berekend waarneembaar dat is alleen readble:

    ko.forcibleComputed = function(readFunc, context, options) {
        var trigger = ko.observable().extend({notify:'always'}),
            target = ko.computed(function() {
                trigger();
                return readFunc.call(context);
            }, null, options);
        target.evaluateImmediate = function() {
            trigger.valueHasMutated();
        };
        return target;
    };
    
    
    myValue.evaluateImmediate();

    Van @mbest reactie https://github.com/knockout/knockout/issues/1019.

    • Wat bedoel je er is geen waarde? Deed het werk voor het schakelen naar deze. Bent u met uitgestelde updates (de algemene instelling). Net besefte dat er mogelijk een conflict op als u verwacht te kunnen bijwerken van de waarneembare en dan onmiddellijk gebruik te maken van de waarde. Als dat zo is probeer het toevoegen van ko.taken.runEarly() om mijn methode.
  4. 1

    stel getCurrentValues() kan verschillende sets van het beperken van de zichtbaarheid
    die zijn gewijzigd elders in de code

    Ik neem aan dat getCurrentValues() is een functie. Als je zou kunnen maken het tot een berekend, uw checkedValueCount zou alleen magisch werk te gaan.

    Kunt u getCurrentValues worden berekend in plaats van een functie?

    • Ik ben oversimplifying mijn werkelijke scenario veel, maar zeker van, laten we zeggen het kan worden (dat zou niet het geval zijn als het bijvoorbeeld nodig om parameters) – ik zie niet in hoe dat enig verschil zou uitmaken. Binnenkant van getCurrentValues() ik ben slicing en dicing andere gegevens om te bepalen welke nodes van een boomstructuur moeten worden geretourneerd. het probleem is dat de functie kan verschillende waarneembare waarden en ik moet de berekende pick-up op. Eigenlijk precies wat de documenten over praten met dynamische afhankelijkheden, maar met de complicatie van hen wordt toegevoegd
    • Zou het een verschil maken als het “slicing en dicing’ was gebaseerd op het beperken van de zichtbaarheid. Bijvoorbeeld, laten we zeggen dat je slicing en dicing de knooppunten die hebben .IsChecked() == true. Je zou dan een berekende genoemd .currentValues() dat zou evalueren van alle knooppunten en de terugkeer van de degenen met .IsChecked(). Kan de slicing en dicing worden gedaan op waarneembare eigenschappen?
    • Ik ben echt niet zeker wat je zegt Juda,elke aanroep kan geen ko waarneembaar in mijn geval – maar nog belangrijker, ik zie niet in hoe dat zou van belang kunnen zijn, knock-out doet geen reflectie over wat sluitingen die u hebt gebeld (ik heb niet gekeken maar als javascript is volledig weg in lisp-land, dit is onmogelijk). De berekende kan doen, is in het beste volgen van een beperking van de zichtbaarheid die worden genoemd.
  5. -1

    want er is geen rechttoe rechtaan manier te dwingen update van een berekende, dat ik gemaakt heb van een waarneembare naam toForceComputedUpdate, en ik noemde het binnen de berekende functie, zodat de berekende zal luisteren naar de update, vervolgens te dwingen update ik noem het zoals dit toForceComputedUpdate(Math.random)

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *