ПредишенСледващото

Превод statideathmood: Как да напишете свой собствен виртуален DOM

Има две неща, които трябва да знаете за да напишете свой собствен виртуален DOM. Ти дори не трябва да се потопите в изходния код реагират или изходния код на всяка друга реализация на виртуална DOM. Те са толкова големи и сложни, но в действителност по-голямата част от виртуалната DOM може да се запише по-малко от 50 реда код. 50. Зума. Код.

Тук го натовари две понятия:

  • Виртуална DOM - всяко представителство на DOM
  • Когато се промени нещо в нашата виртуална DOM дърво, ние създаваме нова виртуална дърво. Алгоритъмът сравнява двете дървета (стари и нови), е разликата и прави само минималните необходимите промени в тази на DOM, за да се поберат виртуалното.

Това е всичко! Нека да се потопите в всеки един от тези понятия.

Представяне на нашата DOM дърво

Ами, на първо място, ние трябва по някакъв начин да запазим DOM дърво в паметта. И ние можем да направим това с прости JS обекти. Да предположим, че имаме едно дърво:

Изглежда просто, нали? Как можем да си го представя с прости JS обекти:

Тук можете да видите две неща:

  • Ние представляваме DOM елементи под формата на обект
  • Ние описваме прост струни JS текст възел

Но да пишат големи дървета по този начин е трудно. Така че нека да напише функция помощник, че ние направихме по-лесно да се разбере структурата:

Сега можем да опишем нашата DOM дърво като такива:

Тя изглежда много по-чист, нали? Но ние дори може да отиде по-далеч. Сигурно сте чували за JSX, нали? Да, бих искал да се прилагат идеите си тук. Е, как действа тя?

Ако четете официалната документация на Бабел за JSX тук. Знаете ли какво Бабел transpiliruet този код:

в нещо като това:

Ами, всъщност го казва Бабел: «Хей, компилира JSX, но вместо React.createElement. заместител ч ». Тук можете да заместите всичко вместо ч. И това ще бъде събрана.

Така че ние пишем DOM, както следва:

И това ще бъде съставен Бабел в следния код:

функция ч връща прост JS обект - нашето възприятие на виртуална DOM.

Опитайте сами по JSFiddle (не забравяйте да Бабел като език).

Използването на нашето представителство DOM

Е, сега ние имаме представа за нашата DOM дърво на JS обект с нашата собствена структура. Това е готино, но трябва по някакъв начин да се създаде реално DOM от него. Разбира се, ние не може да се прилага само нашето разбиране на DOM.

На първо място, нека да се установят някои предположения и се определят някои терминология:

  • Аз ще напиша всички променливи, които съхраняват действителните DOM възли (елементи, текстови възли), като се започне от $. По този начин $ родител елемент ще се DOM
  • Виртуална представителство DOM се съхранява в променлива с име възел
  • Както и в реагира, можете да имате само един корен възел, всички други възли са в рамките на

Сега, когато всичко това ние сме измислили, нека да напише функция createElement (...), който ще се виртуална DOM възел и връща вярно DOM възел. Забравете за дългите подпори и деца. Ние ще се справим с тях по-късно:

По този начин, ние можем да го давате като виртуален текстови възли и възли на виртуални предмети, и той ще работи.

Сега нека да мислим за децата, че всеки един от тях е и възел на текста или елемент. Поради това, те също могат да бъдат създадени с помощта на нашия createElement (...) функция. Ти се чувстваш? Намирисва на рекурсия :)) Така че можем да наречем createElement (...) за всяко от децата си, а след това appendChild () ги в нашата елемент, както следва:

Уау, това изглежда страхотно. Нека оставим настрана реквизита възли. Ще говорим за тях по-късно. Ние не трябва да разберат основните понятия на виртуална DOM и само усложняват.

Да вървим напред и да я изпробвате в JSFiddle.

промените се обработват

Е, ние вече може да се превърне нашата виртуална DOM в реално DOM, че е време да се мисли за сравняване на нашите виртуални дървета. Ние трябва да се напише алгоритъм, който ще сравни две виртуални дърво - стари и нови - и направи само необходимите промени в тази DOM.

Как да се сравни по дърветата? Ние трябва да се справят в следните ситуации:

  • Ако на едно място не е на старите възли: Добавена е възелът, и ние трябва да използваме appendChild (...)
  • Няма нови възли в определено място: този възел е била отстранена, и ние трябва да използваме removeChild (...)
  • Друг възел на това място: възелът се е променило и ние трябва да използваме replaceChild (...)
  • Възлите са едни и същи: ние трябва да отидем по-надълбоко и да се сравнят деца възли

Е, нека напише функция updateElement (...), която се три параметъра: $ майки, newNode и oldNode. $ Майка - майка на реалната DOM нашите виртуални възли. Сега ние виждаме, как да се справят с всички ситуациите, описани по-горе.

Ако няма стари възли

Ако няма нов възел

Тук имаме проблем: ако има един възел на определено място в новата виртуална дървото, ние трябва да го премахнете от реалния DOM. Но как да го направя? Ние знаем, че майка елемент (тя се предава на функцията) и затова трябва да се обадя $ parent.removeChild (...) и да изпратите линк към действителната DOM елемент. Но ние не го правят. Ако знаехме нашата позиция във възела родител, бихме могли да го получите с помощта на parent.childNodes връзка $ [Index], където индекса - позицията на нашите възли в майка елемент.

Добре, нека приемем, че този индекс ще бъде приет в нашия функция (и това е наистина щеше да се случи, както ще видите по-късно), а след това ни код ще бъде:

Нода е променило

На първо място, ние трябва да се напише функция, която сравнява два възела и да ни кажете, ако сайтът е променила много. Ние трябва да имаме предвид, че тя може да бъде елементи, така и текстови възли:

И сега, с текущата родител индекс възел, ние можем лесно да го замени с новосъздадената възел:

Сравнение на подчинените елементи

И не на последно място, ние трябва да премине през всяко дете елемент в двете nodah, да ги сравните и да причини updateElement (...) за всеки от тях. Да, отново рекурсия.

Но има някои неща, които трябва да бъдат разгледани преди писане на код:

  • Трябва да сравнявате децата, ако възелът е елемент (текст възли не могат да имат деца)
  • Сега минаваме препратка към текущия възел като родител
  • Ние трябва да сравните всички деца едно по едно, дори и ако в един момент се получи неопределена (това е добре, нашата функция е да я обработи)
  • И накрая, индекс - това е просто указател към дъщерното възел в масива на деца

Поставянето на всичко заедно

Да, това е то. Направихме го. Сложих всички код в JSFiddle и прилагане наистина е 50 ЗЗД, както съм обещал. Можете да отидете и да играят с него.

Отварящи тях и да видим как да настъпят промени, когато натиснете бутона за презареждане.

заключение

Честито! Направихме го. Написахме виртуално изпълнение на DOM. И тя работи. Надявам се, че след като прочетете тази статия, вие ще разберете основните понятия и как виртуален DOM трябва да работи и как да реагира работи под капака.

  • Поставяне на атрибути и тяхното сравняване и актуализация
  • Добавянето обработват събитие за нашите членове
  • Възможността за нашата виртуална DOM да работи с компоненти като Реагират
  • Първи връзки към възлите на недвижими DOM
  • Използването на виртуалните DOM библиотеки, които пряко мутира недвижими DOM: JQuery и неговите плъгини
  • И още много други ...
Подкрепете проекта - споделете линка, благодаря!