Teraz w zasadzie nic nowego nie stworzymy (no prawie). Poprawimy tylko kardynalny błąd, jakim jest przekazywanie argumentu jako tablicy. Do dzieła!
Nasz poprzedni createElement:
function createElement_v6(type, attributes={}, children=[]){
const childElements = [...children].map(
child =>
child instanceof Object
? child
: createElement_v6("li", {
textContent: child
})
);
return {
type,
children: childElements,
props: Object.assign({ children: childElements }, attributes)
}
}
Przykład użycia 1:
let v6 = createElement_v6("ul", {class: "my-list"}, children = [
"PHP",
"JAVASCRIPT",
'C#'
]
);
console.log(v6);
// Object {
// type: "ul",
// children: (3) [
// 0: Object {
// type: "li",
// children: [],
// props: Object { children: [], textContent: "PHP" }
// }
//
// 1: Object { type: "li", children: [], props: {…} }
//
// 2: Object { type: "li", children: [], props: {…} }
// ],
// props: {
// children: Array(3) [ {…}, {…}, {…} ],
// class: "my-list"
// } }
Przykład użycia 2:
let v6_2 = createElement_v6("ul", {class: "my-list"}, children = [
"PHP",
"JAVASCRIPT",
{
type: "li",
children: [],
props: {
children: [],
textContent: "PHP"
}
}
]
);
console.log(v6_2);
// Object {
// type: "ul",
// children: (3) [
// 0: Object {
// type: "li",
// children: [],
// props: Object { children: [], textContent: "PHP" }
// }
//
// 1: Object { type: "li", children: [], props: {…} }
//
// 2: Object { type: "li", children: [], props: {…} }
// ],
// props: {
// children: Array(3) [ {…}, {…}, {…} ],
// class: "my-list"
// } }
Jak nie rozumiemy, to musimy przerobić lekcje poprzednie + lekcję o variadic functions. Bo takiej funkcji chcemy, a nie tablicy.
I tak jest nieźle – wykonujemy map na kopii tablicy z argumentów. Ale my chcemy mieć …args, które poddajemy wzorcowi concat+map:
function createElement_v7(type, attributes={}, ...children){
const childElements = [...children].map(
child =>
child instanceof Object
? child
: createElement_v7("li", {
textContent: child
})
);
return {
type,
children: childElements,
props: Object.assign({ children: childElements }, attributes)
}
}
W sumie koniec końców obyło się bez concat, spread i rest wystarczył… Oto użycie:
let v7 = createElement_v7("ul", {class: "my-list"},
"PHP",
"JAVASCRIPT",
{
type: "li",
children: [],
props: {
children: [],
textContent: "C#"
}
}
);
console.log(v7);
// Object {
// type: "ul",
// children: (3) [
// 0: Object {
// type: "li",
// children: [],
// props: Object { children: [], textContent: "PHP" }
// }
//
// 1: Object { type: "li", children: [], props: {…} }
//
// 2: Object { type: "li", children: [], props: {…} }
// ],
// props: {
// children: Array(3) [ {…}, {…}, {…} ],
// class: "my-list"
// } }
Sam mam niezły mindfuck od tego wszystkiego, a jeszcze jest to programowanie nieobiektowe, JS-specific i DOM-specific, więc można oczopląsu dostać i żadnego ratunku nie ma.
ServiceLocator to przy tym pikuś. Collection – Composable Query – Queried Collection to przy tym pikuś. Ale gdyby ludzie tak się poddawali, albo korzystali tylko z raz utworzonych wzorców to nie byłoby ani Reacta, ani Hooków.
Tym niemniej polecam małą przerwę i na spokojnie ogarnięcie wszystkiego.