Многие бывшие коллеги и друзья обращались ко мне и спрашивали: «Как вам удалось добиться такой эффективности и скорости при работе в области пользовательского интерфейса?»

Хотя я использую Javascript уже 20 лет, на самом деле опыт - это всего лишь небольшая точка в очень быстро развивающейся экосистеме.

Наибольшее влияние оказал переход на виртуальную модель DOM на основе JSON, что повысило мою производительность как минимум на 200%. Да, это буквально означает, что я могу разрабатывать сложный UI-код в 3 раза быстрее, чем мог раньше.

Поскольку эти концепции все еще в основном неизвестны, я пишу эту статью, чтобы поделиться с вами своими знаниями. Цель состоит в том, чтобы вы также могли извлечь выгоду и перейти на новый уровень разработки фронтенда.

Содержание

  1. Вступление
  2. Что такое виртуальная модель DOM на основе JSON?
  3. Какие свойства я могу использовать на узле vdom?
  4. Какую реализацию мы используем в этой статье?
  5. Краткий обзор усовершенствований системы классов JS neo.mjs
  6. Является ли наша виртуальная структура DOM шаблоном?
  7. Создание нашей первой виртуальной модели DOM на основе JSON
  8. Основные операции VDOM
  9. Изменение нескольких конфигураций
  10. Свойство removeDom vdom
  11. Флаг вдом собственность
  12. Добавление компонентов в компонент (выделение этой статьи)
  13. getVdomRoot ()
  14. Использование самого VDom Engine не является обязательным (выделение этой статьи)
  15. Использование деревьев компонентов
  16. Расширение классов (выделение этой статьи)
  17. Последние мысли

1. Введение

Это будет довольно длинная статья. Пожалуйста, будьте непредубежденными и любопытными, поскольку эти концепции разрушительны.

Прежде чем мы сможем углубиться в преимущества, важно охватить основы.

Я выделил основные моменты этой статьи жирным шрифтом внутри обзора содержания. Я настоятельно рекомендую прочитать статью сверху вниз.

Особенно потрясающе выглядит раздел о расширении классов.

Использование виртуальной модели DOM на основе JSON особенно полезно, если вы хотите создавать сложные компоненты или приложения:

2. Что такое виртуальная модель DOM на основе JSON?

Под этим термином я имею в виду не строку на основе JSON, а вложенную структуру объектов и массивов Javascript в соответствии с синтаксисом JSON.

Проще говоря:

const jsonVdom = JSON.parse(jsonVdomString);

Чтобы дать вам быстрый пример того, как это может выглядеть:

Многие молодые разработчики перестали вникать в это уже на этом этапе.

  1. Подождите, я могу добиться того же в Angular, React или Vue с помощью 3-строчного псевдо-XML-шаблона.
  2. Это не выглядит красиво, так как менее компактно.
  3. Шаблоны псевдо XML лучше соответствуют шаблону DSL (предметно-ориентированный язык).

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

  1. Договорились, немного дольше. Но это не шаблон. Значение: это постоянная структура, которая предназначена для динамического изменения во время выполнения. Вы можете изменить его таким же образом до и после того, как компонент будет смонтирован.
  2. Это не сравнение яблок и апельсинов. Неважно, красиво ли выглядит на первый взгляд. Важно то, что вы можете с этим делать.
  3. Если вы сравните псевдо-XML-шаблон с тем, как выглядит HTML (например, внутри Chrome Dev Tools: Inspect Element), вы правы. Однако JS предоставляет API для работы с узлами DOM, который более объектно-ориентирован. Если вы не сильно любите регулярные выражения, вы согласитесь, что Javascript предназначен для работы с объектами и массивами, а не со строками.

3. Какие свойства я могу использовать на узле vdom?

Внутри реализации neo.mjs мы можем использовать:

Вы можете найти подробную информацию о том, как эти свойства применяются здесь:

Https://github.com/neomjs/neo/blob/dev/src/vdom/Helper.mjs#L262

Суммируя:

  1. тег является самым важным. Вы можете выбрать любые теги HTML или теги пользовательских веб-компонентов.
  2. Механизм vdom полагается на каждый узел, имеющий идентификатор, чтобы выяснить, какие узлы были перемещены в разные места. Вы можете назначить идентификаторы вручную, иначе каждый узел получит автоматически сгенерированный (neo-vnode-x).
  3. html: внутренний HTML-код вашего узла, если он не имеет дочерних узлов.
  4. cn: дочерние узлы с такими же доступными свойствами. Вы можете вложить свою структуру vdom так глубоко, как захотите.
  5. style: вы можете определить свой атрибут стиля как строку. Однако настоятельно рекомендуется придерживаться объектно-ориентированного синтаксиса. Например:
    style: {borderColor: ‘red’, marginRight: ‘10px’, marginTop: ‘-5px’}
    Вы можете использовать camelCase для имен атрибутов стиля.
  6. height, maxHeight, maxWidth, minHeight, minWidth, width - это просто удобные ярлыки, которые будут помещены в объект стиля.
  7. Вы можете вставить любые атрибуты HTML-тега прямо в объект vdom.
    Например: tabIndex: -1
  8. vtype: ‘text’, flag и removeDom будут рассмотрены более подробно позже.

4. Какую реализацию мы используем в этой статье?

Поскольку реализация neo.mjs является наиболее продвинутой, я буду придерживаться ее в этой статье.

neo.mjs - это революционная Javascript Frontend Framework нового поколения, которая позволяет создавать невероятно быстрые многопоточные пользовательские интерфейсы.

В проекте используется лицензия MIT, поэтому вы можете использовать его бесплатно:



Вам не обязательно использовать neo.mjs, если вы хотите использовать виртуальную модель DOM на основе JSON. Лицензия MIT позволяет вам извлекать и использовать реализацию vdom по своему усмотрению. Вы также можете создать собственную реализацию, следуя тем же шаблонам проектирования.

Если вы думаете об использовании neo.mjs, вам следует быстро взглянуть на Workers Setup:

Важной частью этой статьи является то, что VDom Engine находится внутри отдельного потока. Это означает, что все вызовы Engine являются асинхронными.

5. Краткий обзор усовершенствований системы классов JS neo.mjs.

ES6 существует уже давно, поэтому я предполагаю, что вы уже знакомы с системой классов Javascript.

Недостающая часть - это все еще свойства класса.

Чтобы восполнить этот пробел, neo.mjs усовершенствовал классы JS с помощью Custom Config System.

Вкратце: для каждого класса доступен статический метод getConfig ().

Внутри него вы можете указать свойства вашего класса.

Если конфигурация заканчивается подчеркиванием в конце, это сгенерирует для вас afterSetX (), beforeSetX () и beforeGetX ().

Конфиги классов действительно применяются к прототипу класса через Object.defineProperties (). Значение: конфиги применяются как геттеры и сеттеры.

Это позволяет согласованно работать с конфигурациями, поскольку присвоение нового значения запускает установщик.

const myInstance = Neo.create(MyClass, {
    color: blue
});
myInstance.color = 'green'; // triggers the setter

Вот так просто. neo.mjs очень сильно зависит от конфигурации. Вы редко будете вызывать методы и вместо этого будете менять конфигурации.

Вы можете использовать afterSetColor () для сопоставления вашей конфигурации с виртуальной DOM. Вы можете добавить его в разные места. Вы можете проверить другие конфигурации и настроить свою логику по своему усмотрению.

Вы можете использовать beforeSetColor () для логики предварительной обработки (например, чтобы проверить, действительно ли новое значение).

Вы можете использовать beforeGetColor () для изменения значения. Пример: beforeGetController () → если вы получили объект конфигурации, создайте экземпляр контроллера, в противном случае верните экземпляр.

Если вы хотите глубже погрузиться в систему конфигурации (не обязательно читать эту статью):

Https://github.com/neomjs/neo/blob/dev/src/Neo.mjs#L48

Https://github.com/neomjs/neo/blob/dev/src/core/Base.mjs

6. Является ли наша виртуальная структура DOM шаблоном?

Короче: нет.

В качестве примера шаблона:

Https://github.com/shlomiassaf/ngrid/blob/master/libs/ngrid/src/lib/grid/ngrid.component.html

Скорее всего, это следует из лучших практик для фреймворка Angular.

Вы заметите:

  1. Существуют псевдо-теги, куда вы добавляете конфигурации / свойства, такие как атрибуты HTML (может быть сложно отличить, что есть что).
  2. Внутри определений HTML есть переменные.
  3. Внутри шаблона есть операторы if.
  4. Внутри шаблона есть циклы for.

Он компактен и соответствует шаблону DSL, но чем сложнее будут ваши компоненты, тем больше переключателей if & else вам понадобится.

Я видел шаблоны с более чем 1000 строк кода.

Шаблоны не расширяются.

Шаблоны нужно компилировать (что очень дорогое занятие).

Хорошо, существуют компиляторы времени сборки, такие как Svelte, но это предполагает, что ваш шаблон включает все возможные состояния, и вы больше не можете легко расширять или изменять их во время выполнения.

В neo.mjs буквально нет шаблонов. Нет необходимости компилировать структуры, что дает хороший прирост производительности.

Это больше похоже на ручную работу с выводом на основе JSX.

Вы также заметите, что внутри виртуальных структур DOM на основе JSON нет переменных, операторов if или циклов for.

Чтобы действительно понять преимущества, важно прочитать следующие разделы.

7. Создание нашей первой виртуальной модели DOM на основе JSON.

Давайте продолжим работу с нашим файлом MyClass Component, чтобы охватить основы.

Я помещаю этот Компонент в container.Viewport, чтобы отобразить его как приложение neo.mjs. Текущее состояние выглядит так:

В результате DOM выглядит так:

Хотя этот пример пока не выглядит фантастическим, мы уже можем здесь многому научиться.

У нас есть супербазовый скелет vdom, содержащий узел div-оболочки и внутри другого div, содержащего текст и стиль полей.

Поскольку наш div находится внутри приложения, он сразу же будет смонтирован (это необязательно).

внутри метода afterSetColor () мы обращаемся к внутреннему div и присваиваем значение нашей цветовой конфигурации его атрибуту цвета стиля.

Чтобы запустить обновление vdom, мы звоним:

this.vdom = vdom;

Имейте в виду, что это сеттер. Он отправит сообщение электронной почты в VDom Engine внутри VDom worker, чтобы выяснить дельты, в случае, если компонент уже смонтирован. Поскольку он не установлен, когда задано начальное значение, он не запускает Engine.

Добавим консольный журнал:

Мы перезагружаем наше «Приложение» в браузере:
(да, для этого нам не нужны никакие процессы сборки или транспиляции)

Вы заметите, что цвет существует как установщик (выделенная конфигурация с 3 точками), а его значение хранится внутри цвета _.

Мы можем просто изменить значение прямо в консоли:

Наш Компонент сразу настроится:

Внутри нашей консоли мы увидим самое первое дельта-обновление:

Пока что нам понадобилось 2 вызова requestAnimationFrame. Первый для первоначального монтажа приложения, а теперь второй для изменения цветового стиля.

Есть 3 разных способа назначить наши изменения объекту vdom:

this.vdom = vdom;

Использование символа подчеркивания в начале не приведет к вызову Engine.

this._vdom = vdom; // silent update

Поскольку наше обновление является асинхронным, мы можем использовать обратный вызов:

this.promiseVdomUpdate().then(() => {
    // do something after the delta update got applied to the DOM
});

8. Основные операции VDOM.

Давайте немного изменим наш первый пример:

Мы изменили нашу цветовую конфигурацию на itemHeight и немного скорректировали скелет нашего vdom. Как уже упоминалось, JS идеально подходит для работы с объектами и массивами, поэтому мы можем просто перебирать наши элементы.

Нам не нужно сохранять статический скелет нашего vdom. Давайте динамически добавим новый элемент:

afterSetItemHeight(value, oldValue) {
    let vdom = this.vdom;

    vdom.cn.push({style: {backgroundColor: 'blue'}});

    vdom.cn.forEach(item => {
        item.style.height = value;
    });

    this.vdom = vdom;
}

Мы не будем делать это внутри этого метода установки itemHeight, но просто для того, чтобы понять идею.

afterSetItemHeight(value, oldValue) {
    let vdom = this.vdom;

    vdom.cn.forEach(item => {
        item.style.height = value;
    });

    vdom.cn.push(vdom.cn.shift());

    this.vdom = vdom;
}

Мы удалили первый элемент и добавили его в конец массива элементов.

Поскольку это происходит до монтирования Компонента, наши идентификаторы по-прежнему будут создаваться по возрастанию (1, 2, 3) из измененного порядка элементов.

Давайте изменим конфиг itemHeight внутри Консоли:

Теперь наш порядок элементов равен 2, 3, 1. Давайте посмотрим на обновления дельты:

Подсказка: VDom Engine может обрабатывать любую комбинацию изменений одновременно.

Я выбрал пример, чтобы добавить первый элемент в конец нашего массива с определенной целью.

vdom.cn.push(vdom.cn.shift());

Вы можете легко сделать это в обратном направлении:

vdom.cn.unshift(vdom.cn.pop());

Вариант использования - бесконечная прокрутка. Представьте, что вы хотите создать представление календарного месяца и при прокрутке недель вы хотите динамически добавлять новые строки недель вверху и удалять строки внизу (или наоборот).

Вы можете посмотреть на реализацию здесь:

Https://github.com/neomjs/neo/blob/dev/src/calendar/view/MonthComponent.mjs#L410

Как бы вы реализовали логику загрузки магазина? Для этого нам нужно перебрать данные:

Поскольку мы можем загружать наш магазин несколько раз, мы действительно хотим сбросить массив элементов перед добавлением новых элементов. Ну, если мы не хотим динамически добавлять больше.

9. Изменение нескольких конфигураций

Давайте изменим код, чтобы реализовать кнопку, содержащую 2 конфигурации:
iconCls & text.

Давайте быстро посмотрим на результат:

Внутри afterSetIconCls () мы хотим удалить старый iconCls, если он существует. NeoArray может быть в этом удобным помощником.

Прежде чем динамически менять конфиги, давайте вспомним, что происходит:

Изменение конфигурации в нашем сценарии использования Button вызовет VDom Engine.

Это происходит асинхронно (движок живет внутри воркера).

Когда вы инициируете изменение, мы отправим наш новый объект vdom, а также объект vnode (содержащий предыдущее состояние) в класс vdom.Helper. Он преобразует новый объект vdom во vnode и сравнит старый и новый vnodes, чтобы выяснить дельты.

После завершения операции новый vnode будет назначен нашему компоненту. Если произойдет новый вызов Engine, до того, как вернется новый vnode, вы можете столкнуться с серьезными проблемами.

const myButton = Neo.create(MyClass, {id: 'myButton'};
setTimeout(() => {
    myButton.iconCls = ['fa', 'fa-user'];
    myButton.text    = 'New Text
}, 1000);

Делаем это внутри консоли:

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

Однако 2 обновления - это не то, что нам нужно.

const myButton = Neo.create(MyClass, {id: 'myButton'};
setTimeout(() => {
    myButton.set({
        iconCls: ['fa', 'fa-user'],
        text   : 'New Text'
    });
}, 1000);

Это потрясающе.

Мы также получаем обратный звонок, как вы можете видеть в журнале Promise ‹pending›.

myButton.set({
    iconCls: ['fa', 'fa-user'],
    text   : 'New Text'
}).then(() => {
    // do something when done
});

Мы также можем использовать setSilent (), если мы вообще не хотим запускать VDom Engine.

10. Свойство removeDom vdom

Работа с полностью динамическими структурами может быть сложной. Давайте придерживаться нашего примера с кнопкой с изменением, которое мы не хотим сохранять, и узлом iconCls или text span внутри DOM, если значение отсутствует.

Без конфигурации removeDom нам нужно было бы сделать что-то вроде:

Не включая здесь код, так как это не то, что нам следует делать.

В случае, если мы удалим узел iconCls в случае отсутствия iconCls, нам также необходимо воссоздать его, если мы изменим конфигурацию iconCls. Для textNode нам нужно проверить, есть ли iconNode на месте или нет.

Эта логика даже не заключается в удалении и повторном добавлении textNode.

Теперь представьте более сложный компонент с несколькими конфигурациями → узлы, которые не являются обязательными. Мы могли бы использовать свойство vdom flag, чтобы найти нужные места, но это все равно будет кошмаром.

Итак, как мы можем решить эту проблему с помощью свойства removeDom?

Все, что нам нужно сделать, это пометить компонент, чтобы он был удален из реальной DOM, в случае, если нет значения.

Обратите внимание, что iconCls теперь имеет значение по умолчанию null.

Наша кнопка отображается без узла диапазона iconCls.

Давайте изменим нашу кнопку внутри консоли и добавим iconCls плюс одновременно удалим текст:

Мы удалили textNode и повторно добавили наш iconNode.

Он даже сохранит тот же идентификатор, если вы удалите и повторно добавите его несколько раз.

Мне очень понравилась эта функция, поскольку она позволяет нам сохранить структуру vdom.

11. Флаг вдом собственности.

До сих пор мы обращались к дочерним узлам напрямую, например

vdom.cn[0]

Это самый быстрый способ, который отлично подходит для тривиальных структур.

А теперь представьте себе несколько «настоящих живых» структур:

Что ж, очевидно, что вы все еще можете напрямую получить доступ к своему узлу.

Хотя это не весело. Если ваши конструкции станут динамичными, это станет практически невозможным.

Давайте попробуем это еще раз, используя свойство flag:

Импортируем утилит.Вдом. Мы добавляем свойство flag к нашему целевому узлу. Не беспокойтесь, этот не попадет в настоящий DOM.

Флаги не обязательно должны быть уникальными. Хотя getByFlag () возвращает первый найденный флаг, вы также можете использовать getFlags () для получения всех узлов, содержащих определенный флаг.

Обратите внимание, что мы передали узел верхнего уровня vdom.

В случае, если наше дерево действительно велико, мы также можем передать дочерний узел, чтобы уменьшить область поиска (производительность).

vdom.Util заслуживает более внимательного изучения, поскольку он предоставляет больше методов для поиска определенных узлов (по классу, стилю или в целом по любой комбинации свойств узла.

Https://github.com/neomjs/neo/blob/dev/src/util/VDom.mjs

12. Добавление компонентов в компонент

Меня только что спросили, можно ли добавить фильтры на основе столбцов в table.Container.

table.Container получил новую конфигурацию: showHeaderFilters_: false, которая будет передана соответствующему экземпляру header.Toolbar, который затем передаст его в header.Button.

Таким образом, мы можем просто включить или выключить его в самом tableContainer.

Чтобы действительно понять, насколько мощной может быть виртуальная модель DOM на основе JSON, давайте подробнее рассмотрим table.header.Button:

Https://github.com/neomjs/neo/blob/dev/src/table/header/Button.mjs#L217

Вы можете многому научиться из этого крошечного фрагмента кода.

Если мы установим для конфигурации showHeaderFilter значение true для экземпляра headerButton, мы проверим, есть ли у этого Компонента уже экземпляр filterField или нет.

Если this.filterField еще не существует, мы используем Neo.create () для создания экземпляра. Вы можете использовать editorFieldConfig для изменения любых конфигураций редактора, который вам нравится. Это включает модуль, поэтому вы можете легко переключиться на SelectFields, CheckBoxes или что вам больше нравится.

После вызова create () у нашего нового экземпляра уже есть свойство vdom, включая начальное состояние всех переданных конфигураций.

Итак, все, что нам нужно сделать, это отбросить поле vdom в любом месте заголовка.

me.vdom.cn.push(me.filterField.vdom);

Так просто.

В случае, если мы установили для конфигурации showHeaderFilter значение false, мы просто снова используем флаг removeDom. Значение: экземпляр JS (и его состояние) сохраняется, а мы просто удаляем или повторно добавляем реальный DOM.

Также стоит взглянуть на логику отображения или скрытия полей редактора:

Https://github.com/neomjs/neo/blob/dev/src/table/header/Toolbar.mjs#L55

Мы выполняем автоматические обновления для каждой кнопки заголовка, а затем запускаем обновление vdom для панели инструментов, содержащей кнопки. Результат - всего 1 вызов Engine.

Внутри цикла forEach мы могли бы также использовать:

item.showHeaderFilter = value;

Это вызовет одно обновление для каждого экземпляра Button отдельно. Эти обновления могут выполняться параллельно, поскольку для каждой кнопки нет пересечения vdom.

Приятно то, что вы сами решаете, когда и что обновлять.

Недавно я добавил свойство removeDom в элементы макета карточек. Значение: все неактивные (невидимые) карточки удаляются из реальной модели DOM.

Результат был невероятным: размер dom для большинства демонстрационных приложений был уменьшен на 80% + при сохранении полной функциональности (включая состояние и даже состояния прокрутки).

Хотя вы можете утверждать, что это отображение: ни один из узлов не получает никаких вычислений макета на основе браузера, сокращение оказало огромное влияние на использование памяти основным потоком, что привело к повышению производительности.

13. getVdomRoot ()

Наш самописный пример кнопки был довольно близок к реальной реализации:

Теперь для table.header.Button мы хотели бы, чтобы эта кнопка была вложена в узел оболочки.

Вы заметите, что структура почти такая же, просто заключена в тег th.

Теперь мы действительно хотим, чтобы наши методы afterSetX () обращались к «тем же» узлам, и мы хотим, чтобы все наши конфигурации верхнего уровня (например, cls на уровне компонентов) снова применялись к тегу кнопки.

getVdomRoot () легко решает эту проблему. Нам также необходимо настроить getVnodeRoot () на тот же уровень из соображений согласованности (например, поля формы изменяют vnode (предыдущее состояние) в случае, если пользователь вводит в них).

14. Использование самого VDom Engine необязательно.

Если вы все еще скептически относитесь к концепциям виртуальной DOM на основе JSON, эта часть должна вас убедить.

Представьте, что у вас есть такая таблица:

Если вы хотите обновить все ячейки случайным образом, это приведет к 1800 одиночным вызовам дельта-обновления.

Конечно, мы могли бы сгруппировать их и передать полное табличное представление в VDom Engine, но в случае, если мы будем использовать SocketConnection и реально получать данные для одной ячейки за раз, мы определенно не хотим анализировать все представление.

Мы точно знаем, какая ячейка изменилась и каким должно быть новое содержимое.

При обновлении ячеек вручную на моем компьютере получается 20 requestAnimationFrames со скоростью 60 кадров в секунду около 300 мс.

Вы можете далеко не увидеть все изменения.

Https://neomjs.github.io/pages/node_modules/neo.mjs/dist/production/examples/tableStore/index.html

Подсказка: демоверсия работает быстрее при закрытой консоли, поскольку 1800 журналов обновлений замедляют ее.

Https://github.com/neomjs/neo/blob/dev/src/table/View.mjs#L217

Если вы отправляете объект vdom в VDom Engine, это создаст дельты и передаст их основному потоку.

Очевидно, вы можете просто вручную создать эти вызовы обновления и отправить их из своей области (работника приложения) непосредственно в основной поток.

Мы также настраиваем vdom незаметно, чтобы сохранить состояние на месте.
(Чтобы сделать это на 100% правильно, нам также необходимо настроить vnode, запрос функции.)

Демонстрация Helix Performance использует ту же стратегию для обновлений вручную:

Если я очень быстро прокручиваю по горизонтали (Magic Mouse или TrackPad), я получаю до 30 000 обновлений дельты в секунду на моем компьютере.

Попытайся:

Https://neomjs.github.io/pages/node_modules/neo.mjs/dist/production/examples/component/coronaHelix/index.html

15. Использование деревьев компонентов

Деревья компонентов - это, по сути, слой абстракции над деревом vdom.

Https://github.com/neomjs/neo/blob/dev/apps/covid/view/MainContainer.mjs#L39

Если вы работаете с контейнерами, вы можете просто перетащить компоненты (или объекты конфигурации компонентов) в массив элементов и использовать макеты (например, flexbox или card).

Хотя это действительно необязательно. Если вы предпочитаете придерживаться самого дерева vdom, это вполне нормально.

Поскольку само дерево компонентов также основано на JSON, вы можете очень легко смешать его с виртуальной DOM на основе JSON.

17. Расширение классов

Конечно, вы также можете расширять классы в Angular, React или Vue, но реально расширить ваши шаблоны просто невозможно.

Теперь в neo.mjs это можно сделать. Я бы не рекомендовал переопределять весь объект vdom, но вы можете добавить новые конфигурации в свой расширенный класс. Они могут изменить ваш объект vdom, чтобы добавить дополнительные функции (дочерние узлы) или изменить существующие.

Конечно, вы также можете переопределить методы afterSetX ().

Что ж, это, скорее всего, приведет к 2 вызовам VDom Engine, если предположить, что ваш родительский метод также изменяет vdom.

Однако вы можете использовать флаг silentVdomUpdate, чтобы предотвратить это, и вы получите всего 1 вызов VDom Engine.

Удивительно, правда?

16. Заключительные мысли

Если вы дочитаете до этого места, я очень горжусь вами.

Эта статья была не только длинной, но и непростой для понимания на первый взгляд.

Несмотря на то, что я создал эту виртуальную реализацию DOM самостоятельно, я все еще лишь поверхностно оцениваю то, что с ее помощью возможно.

Если вы понимаете основные концепции, следующий шаг для вас - погрузиться в базу кода neo.mjs:



Теперь вы готовы взглянуть на некоторые из более сложных компонентов и действительно понять, что происходит.

Теперь вы также готовы создать свои первые виртуальные компоненты DOM на основе JSON самостоятельно!

Я с нетерпением жду возможности увидеть, что с ним могут сделать такие талантливые разработчики, как вы. Вы можете добавить PR в репо, если вы создали новый пример или компонент, который вы хотели бы продемонстрировать (или просто получить обзор).

Спасибо, что прочитали это, и счастливого кодирования,
Тобиас