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 ...