Faktorální
The produkt z (=výsledek) a celé číslo a všechny celá čísla pod tím
Čtyři faktoriály (4 x 3 x 2 x 1) jsou 24
Cíl
Vytvořte faktoriální komponentu, která bude počítat odpověď rekurzivně pouze pomocí šablon a pomocníci .
Krok 1 – Jak vypočítat faktoriál pomocí rekurze
Podívejme se nejprve, jak vyřešit faktoriál pomocí rekurze v JS zemi
function factorial(number) {
if(number === 0) return 1; //when we get to the base case it returns 1.
return number * factorial(number-1) //Recursion, we are calling factorial again with n-1
}
factorial(3) //6
Krok 2 – Faktorová složka
Napíšeme totéž, ale pomocí šablon ember (toto není konečná verze) je účelem ukázat podobnost s ekvivalentem js
ekv je pomocník pro testování rovnosti {{eq "hola" "bye"}} = false
sub je pomocník k odečtení něčeho {{sub 5 1}} = 4
více je pomocník k vynásobení něčeho {{mult 5 2}} = 10
Tyto a další pomocníky najdete na
žhaví-matematickí-pomocníci
uhlík-pravda-pomocníci
{{! factorial.hbs}}
{{#if (eq @number 0)}}
{{return 1}} {{! when we get the base case, it retuns 1.}}
{{else}}
{{return
(mult @number <Factorial @number={{sub @number 1}} />)
}} {{! Recursion, we're calling factorial again with n-1}}
{{/if}}
Tento algoritmus se zdá správný a koncepčně je stejný jako JS
ekvivalentní, ale obsahuje některé chyby.
Za prvé, když chcete return
něco v ember šablonách, použijete yield
klíčové slovo místo return
{{! factorial.hbs}}
{{#if (eq @number 0)}}
{{yield 1}} {{! when we get to the base case, return 1.}}
{{else}}
{{yield
(mult @number <Factorial @number={{sub @number 1}} />)
}} {{! Recursion, we're calling factorial again with n-1}}
{{/if}}
Nakonec je to ta obtížná část, kde se ocitáme trochu ztraceni, zatímco ve skutečnosti může poskytnout nebo „vrátit“ součást
{{yield (component 'factorial' @number=(sub @number 1)}}
Tato komponenta by se ve skutečnosti nespustila, takže klient tohoto kódu by musel udělat něco takového.
{{#let 10 as |number|}}
<Factorial @number={{number}} as |Factorial|>
<Factorial />
</Factorial>
{{/let}}
Což vlastně nic nedělá, protože nikdy nedostaneme odpověď.
Tady je řešení
{{! factorial.hbs}}
{{#if (eq @number 0)}}
{{yield 1}} {{! when we get to the base case, return 1.}}
{{else}}
{{! Recursion, we are calling factorial component again with n-1}}
<Factorial @number={{sub @number 1}} as |answer|>
{{yield (mult @number answer)}}
</Factorial>
{{/if}}
Vynásobením aktuálního čísla odezvou jiného faktoriálu (n-1) (uvnitř bloku) , právě jsme pokryli rekurzi.
Zde je konečná komponenta "API".
{{#let 10 as |number|}}
<Factorial @number={{number}} as |answer|>
<h1>{{number}}! is {{answer}}</h1>
</Factorial>
{{/let}}
Nakonec, pokud chceme vizuálně zobrazit nebo vykreslit rekurzivní strom pěkně, můžeme použít <ul>
štítek
{{! factorial.hbs}}
{{#let
(array "red" "blue" "yellow" "orange" "pink") as |colors|
}}
<ul style="background-color: {{object-at (mod (sub @number 1) colors.length) colors}};">
{{#if (eq @number 0)}}
{{yield 1}} {{! when we get to the base case, return 1.}}
{{else}}
{{@number}} * factorial({{sub @number 1}})
{{! Recursion, we are calling factorial component again with n-1}}
<Factorial @number={{sub @number 1}} as |response|>
{{yield (mult @number answer)}}
</Factorial>
{{/if}}
</ul>
{{/let}}
A inspektor Ember by vypadal takto!
Zde je ukázka
Proč používat šablony místo čistého JavaScriptu?
Šablony Ember se automaticky vykreslí, když nějaká hodnota (musí být @tracked
zdobená nemovitost nebo vlastnost Ember.Object) v nich odkazované změny, to znamená, že bychom mohli mít pozorovanou rekurzi. Náš strom komponent může skutečně činit chytrá rozhodnutí, takže můžeme mít rekurzivní logický strom, který přepočítává libovolné události, jako je kliknutí na tlačítko, které by mohlo zvýšit vlastnost, na kterou šablona odkazuje, a spustit překreslení atd. Jinými slovy, můžeme využít toho, že šablony ember již přesně vědí, kdy se mají „překreslit“ jako efektivní pozorovatelé naší rekurze.
Tento druh problémů můžete samozřejmě vyřešit také přidáním pozorovatelů do vaší třídy komponent js nebo jinou technikou, která je obvykle mnohem podrobnější a vyžadovala by nějaký druh ručního zapojení pozorovatelů přes addObserver
a pak je zničte, pokud se komponenta zničí.
O našem případu použití
Tento krátký blogový příspěvek je o něčem, co jsem se dnes se svými kolegy naučil, když jsem se pokoušel vypočítat hodnotu pomocí rekurzivní techniky na šablonách žhavých uhlíků , kterou jsme nakonec nepoužili.
Náš případ použití byl velmi zvláštní a specifický, chtěli jsme způsob, jak zmenšit složitý vnořený objekt (sloučit objekt) a vytvořit živý pole, takže klient mohl iterovat dál. Tento „živý“ obsah by používal šablony "pozorovatelnost" a automatické "vykreslování" pro efektivní pozorování externí závislosti, tj. DS.Model
instanci, protože proces zploštění má logické větve založené na DS.Model
vlastnosti skutečné hodnoty (odkazované v šablonách). Od jakékoli změny v DS.Model
by způsobilo kompletní překreslení a dopady na výkon byly hrozné, zvolili jsme jinou cestu.