Hogyan kell írni saját virtuális dom - devschacht - medium
Fordítás a cikk deathmood: Hogyan kell írni a saját Virtual DOM
Két dolgot kell tudnia a saját virtuális DOM írásához. Nem is kell merülnie a React forráskódjába vagy a virtuális DOM bármely más megvalósításának forráskódjába. Olyan nagyok és összetettek, de a valóságban a virtuális DOM nagy része kevesebb, mint 50 sornyi kóddal írható. 50. Sorok. Kódot.
Itt két fogalom létezik:
- Virtuális DOM - a jelenlegi DOM bármely ábrázolása
- Amikor megváltoztunk valamit a virtuális DOM-fáinkban, létrehozunk egy új virtuális fát. Az algoritmus összehasonlítja a két fát (régi és új), megtalálja a különbséget, és csak a szükséges minimális módosításokat teszi a jelenlegi DOM-ba, hogy megfeleljen a virtuálisnak.
Ez minden! Gondoljunk bele ezekre a fogalmakra.
DOM-fa nézete
Nos, először is meg kell néznünk a DOM fát a memóriában. És ezt egyszerű JS objektumokkal tehetjük meg. Tegyük fel, hogy van ez a fa:
Egyszerűnek tűnik, nem igaz? Hogyan lehet ezt elképzelni egyszerű JS objektumokkal:
Itt két dolgot észlelhet:
- Az objektum nézetben a DOM elemeket képviseljük
- Szöveges csomópontokat egyszerű JS karakterláncokkal írunk le
De elég nehéz írni ilyen nagy fákat. Szóval írjunk egy kiegészítő funkciót, hogy könnyebben megértsük a struktúrát:
Most leírhatjuk a DOM fájtunkat ebben a formában:
Nagyon tisztábbnak tűnik, ugye? De még tovább is megyünk. Hallottál már a JSX-ről, ugye? Igen, itt szeretném alkalmazni ötleteit. Szóval, hogyan működik?
Ha elolvassa a Babel hivatalos dokumentációját a JSX-re. tudod, hogy Babel fogja lefordítani ezt a kódot:
valami ilyesmiben:
Nos, ő azt mondja Bábelnek: "Hé, készítsd el ezt a jsx-et, de a React.createElement helyett. helyettesítő h. " Itt bármikor helyettesíthet bármit. És össze fogják állítani.
Tehát a DOM-ot így írjuk:
Ezt a Babel fogja összeállítani a következő kóddal:
A h függvény végrehajtása egy egyszerű JS objektumot ad vissza - a virtuális DOM ábrázolását.
Próbáld ki magad a JSFiddle-en (ne felejtsd el megadni a Babel nyelvet).
DOM nézetünk alkalmazása
Nos, most már megnézzük a JS objektum DOM fáit, saját struktúrával. Hűvös, de valahogy ki kell hoznunk egy igazi DOM-ot. Természetesen nem csak a DOM-hoz alkalmazhatjuk véleményünket.
Először is készítsünk néhány feltételezést és definiáljuk a terminológiát:
- A tényleges DOM csomópontokat (elemeket, szöveges csomópontokat) tároló változók megírása, kezdődően $. így $ szülő egy igazi DOM elem
- A virtuális DOM-ábrázolás egy csomópont nevű változóban tárolódik
- Mint a React esetében, csak egy gyökércsomópont lehet, minden más csomópont belsejében van
Most, hogy rendeztük ki, írjuk a createElement (...) függvényt, amely egy virtuális DOM csomópontot vesz és visszaadja az igazi DOM csomópontot. Felejtsd el a kellékeket és a gyerekeket. később foglalkozunk velük:
Így mindkét virtuális szöveges csomópontot és a virtuális elem csomópontokat átadhatjuk, és ez működni fog.
Gondoljunk csak a gyerekekre: mindegyikük szöveges csomópont vagy elem is. Ezért létrehozhatók a createElement (...) függvény segítségével is. Érzi? A rekurzió szaga :)) Így felhívhatjuk a createElement (...) minden egyes gyermek elemre, majd a következő elemre illeszthetjük őket:
Hű, remekül néz ki. Távolítsuk el a rekeszcsomópontokat most. Majd később beszélünk róluk. Nem kell nekünk a virtuális DOM-koncepciók alapvető megértéséhez, és csak komplexitást fognak felvenni.
Menjünk előre, és próbáljuk meg ezt a JSFiddle-ben.
A változtatások feldolgozása
Nos, most a virtuális DOM-ot egy igazi DOM-ba fordíthatjuk, itt az ideje, hogy átgondolhassuk virtuális fáinkat. Meg kell adnunk egy algoritmust, amely két virtuális fát hasonlít össze - régi és új -, és csak a szükséges változtatásokat teszi a jelenlegi DOM-ban.
Hogyan viszonyulsz a fákhoz? A következő helyzeteket kell kezelnünk:
- Ha nincs egy adott csomópont egy adott helyen: hozzáadta a csomópontot, és használnunk kell az appendChild (...)
- Nincs új csomópont egy adott helyen: ez a csomópont eltávolításra került, és eltávolítanunk kell (...)
- Egy másik csomópont ezen a helyen: a csomópont megváltozott, és cserélni kell (...)
- A csomópontok ugyanazok: mélyebbre kell mennünk, és összehasonlítjuk a gyermekcsomókat
Nos, írjuk a updateElement (...) függvényt, amely három paramétert tartalmaz: $ parent, newNode és oldNode. $ szülő a virtuális csomópont valós DOM szülője. Most látjuk, hogyan kell kezelni az összes fent leírt helyzetet.
Ha nincs egy régi csomópont
Ha nincs új csomópont
Itt van egy probléma: ha nincs egy csomópont egy adott helyen az új virtuális fában, azt el kell távolítanunk az igazi DOM-ból. De hogyan lehet ezt tenni? Ismerjük a szülőelemet (átadjuk a függvénynek), ezért a $ parent.removeChild (...) szót kell hívnunk és át kell adnunk a referenciát az aktuális DOM elemre. De nekünk nincs. Ha tudnánk a szülőnkben lévő csomópontunk helyzetét, akkor a $ parent.childNodes [index] -re hivatkozhatunk, ahol az index a csomópontunk pozíciója a szülőelemben.
Nos, tegyük fel, hogy ez az index átkerül a funkciónkra (és ez tényleg meg fog történni, ahogy később látni fogjuk), akkor a kódunk így lesz:
Noda megváltozott
Először is meg kell adnunk egy függvényt, amely összehasonlítja a két csomópontot, és elmondja nekünk, hogy a csomó tényleg megváltozott-e. Figyelembe kell venni, hogy lehet elem vagy szöveg csomópont:
És most, ha az aktuális csomópont csomópontjának indexe könnyen helyettesíthető az újonnan létrehozott csomóponttal:
A gyermekelemek összehasonlítása
Végül, de nem utolsósorban mindkét csomóponton meg kell haladnunk minden egyes gyermekelemet, össze kell hasonlítanunk őket, és mindegyiküknek frissíteniük kell a (z) ... frissítést (...). Igen, ismét, rekurzió.
De van néhány dolog, amit figyelembe kell venni a kód megírása előtt:
- Összehasonlítjuk a gyerekeket, ha a csomópont egy elem (a szövegcsomópontok nem rendelkeznek gyermekekkel)
- Most átadjuk a hivatkozást az aktuális csomópontra, mint szülő
- Összehasonlítjuk az összes gyermeket egyenként, még akkor is, ha egy bizonyos ponton meghatározatlan (ez normális, funkciójuk tudja kezelni)
- Végül, az index csak egy mutató a gyermekcsomópontnak a gyerekek tömbjében
Összeszereljük
Igen, ez az. Megérkeztünk. Az összes kódot a JSFiddle-hez tettem, és a megvalósítás valóban 50 LOC, ahogy ígértem. Menj és játssz vele.
Nyissa meg a fejlesztői eszközöket, és nézze meg, hogy a változtatások mikor történtek az Újrahívás gombra kattintva.
következtetés
Gratulálunk! Megcsináltuk. Megírtuk a virtuális DOM implementációját. És működik. Remélem, hogy miután elolvastad ezt a cikket, megérted az alapvető fogalmakat, és hogyan működik a virtuális DOM, és hogyan működik a React a motorháztető alatt.
- Elem attribútumok beállítása, összehasonlítása és frissítése
- Eseménykezelők hozzáadása elemeinkhez
- A virtuális DOM-nak az olyan komponensekkel való együttműködése, mint a React
- Linkek a valódi DOM csomópontokhoz
- Virtuális DOM használata olyan könyvtárakkal, amelyek közvetlenül módosítják a valódi DOM-ot: a jQuery és a plug-inje
- És még sok más ...