UXPUB 🇺🇦 Дизайн-спільнота

Cover image for Швидкий гайд з Preact. Віртуальний DOM
Victor Demushkin
Victor Demushkin

Опубліковано • Оновлено

Швидкий гайд з Preact. Віртуальний DOM

Якщо написаний вами JavaScript став настільки складним, що ним важко керувати – на допомогу може прийти Preact.

Preact надає інструменти, необхідні для створення складних веб-додатків із невеликих шматочків багаторазового використання, які називаються компонентами. Унікальність Preact в тому, що він надає ці інструменти в унікально невеликому пакеті: лише 3 Кб коду JavaScript або приблизно одна сторінка тексту. Саме тому сайти з великим трафіком, такі як IKEA, Bing, Etsy та інші, використовують Preact

Використання без компіляції

Preact упакований для використання безпосередньо у браузері, і не потребує жодної збірки чи інструментів:

<script type="module">
  import { h, Component, render } from 'https://unpkg.com/preact?module';

  // Create your app
  const app = h('h1', null, 'Hello World!');

  render(app, document.body);
</script>
Увійти у повноекранний режим Вихід із повноекранного режиму

Основним недоліком розробки таким чином є відсутність JSX, який вимагає етапу збірки. Але є ергономічна та продуктивна альтернатива JSX.

Альтернативи JSX

Написання викликів h або createElement може бути виснажливим. Перевага JSX полягає в тому, що він виглядає схожим на HTML, що полегшує його розуміння багатьом розробникам. Однак для JSX потрібен етап збірки, тому ми настійно рекомендуємо альтернативу під назвою HTM.

HTM — це JSX-подібний синтаксис, який працює в стандартному JavaScript. Замість етапу створення він використовує власний синтаксис тегованих шаблонів JavaScript, який було додано в 2015 році та підтримується в усіх сучасних браузерах. Це більш популярний спосіб написання додатків Preact.

<script type="module">
  import { h, Component, render } from 'https://unpkg.com/preact?module';
  import htm from 'https://unpkg.com/htm?module';

  // Initialize htm with Preact
  const html = htm.bind(h);

  function App (props) {
    return html`<h1>Hello ${props.name}!</h1>`;
  }

  render(html`<${App} name="World" />`, document.body);
</script>
Увійти у повноекранний режим Вихід із повноекранного режиму

Порада: HTM також надає зручну версію Preact для одного імпорту:

import { html, render } from 'https://unpkg.com/htm/preact/index.mjs?module'
Увійти у повноекранний режим Вихід із повноекранного режиму

Віртуальний DOM

Чим "віртуальний" DOM ​​відрізняється від справжнього DOM, який ми використовуємо під час програмування для браузера?

Віртуальний DOM (Virtual DOM) — це простий опис деревовидної структури за допомогою об’єктів:

let vdom = {
  type: 'p',         // a <p> element
  props: {
    class: 'big',    // with class="big"
    children: [
      'Hello World!' // and the text "Hello World!"
    ]
  }
}
Увійти у повноекранний режим Вихід із повноекранного режиму

Такі бібліотеки, як Preact, надають спосіб створення цих описів, які потім можна синхронізувати з деревом DOM браузера. З синхронізацією кожної частини дерева DOM-дерево браузера оновлюється відповідно до структури, описаної віртуальним DOM-деревом.

Це корисний інструмент, оскільки він дозволяє нам створювати інтерфейс користувача декларативно, а не імперативно. Замість того, щоб описувати, як оновити DOM у відповідь на такі речі, як введення з клавіатури чи миші, нам потрібно лише описати, як має виглядати DOM після отримання цього введення. Це означає, що ми можемо неодноразово надавати Preact описи деревоподібних структур, і він оновлюватиме дерево DOM браузера відповідно до кожного нового опису – незалежно від його поточної структури.

У цьому розділі ми дізнаємося, як створювати віртуальні дерева DOM і як наказати Preact оновлювати DOM відповідно до цих дерев.

Створення віртуальних дерев DOM

Існує кілька способів створення віртуальних дерев DOM:

  • createElement(): функція, надана Preact
  • JSX : HTML-подібний синтаксис, який можна скомпілювати до JavaScript
  • HTM : HTML-подібний синтаксис, який можна писати безпосередньо в JavaScript

Корисно почати з найпростішого підходу, яким буде прямий виклик createElement() функції Preact:

import { createElement, render } from 'preact';

let vdom = createElement(
  'p',              // a <p> element
  { class: 'big' }, // with class="big"
  'Hello World!'    // and the text "Hello World!"
);

render(vdom, document.body);
Увійти у повноекранний режим Вихід із повноекранного режиму

Наведений вище код створює віртуальний DOM "опис" елемента абзацу. Першим аргументом для createElement є ім’я елемента HTML. Другим аргументом є "props" елемента - об'єкт, що містить атрибути (або властивості), які потрібно встановити для елемента. Будь-які додаткові аргументи є дочірніми для елемента, які можуть бути рядками (наприклад, 'Hello World!') або елементами Virtual DOM із додаткових createElement() викликів.

Останній рядок повідомляє Preact створити справжнє дерево DOM, яке відповідає нашому «опису» віртуальний DOM, і вставити це дерево DOM у <body> веб-сторінки.

Тепер ще більше JSX!

Ми можемо переписати попередній приклад за допомогою JSX, не змінюючи його функціональність. JSX дозволяє нам описувати наш елемент абзацу за допомогою HTML-подібного синтаксису, який може допомогти зберегти читабельність, коли ми описуємо складніші дерева. Недоліком JSX є те, що наш код більше не пишеться на JavaScript і має бути скомпільований таким інструментом, як Babel. Компілятори виконують роботу з перетворення наведеного нижче прикладу JSX у точний createElement() код, який ми бачили в попередньому прикладі.

import { createElement, render } from 'preact';

let vdom = <p class="big">Hello World!</p>;

render(vdom, document.body);
Увійти у повноекранний режим Вихід із повноекранного режиму

Тепер він набагато більше схожий на HTML!

Є ще одна річ, про яку слід пам’ятати про JSX: код всередині елемента JSX (у кутових дужках) є спеціальним синтаксисом, а не JavaScript. Щоб використовувати синтаксис JavaScript, наприклад числа чи змінні, вам спочатку потрібно «вискочити» з JSX за допомогою {expression} - подібно до полів у шаблоні. У наведеному нижче прикладі показано два вирази: один для встановлення class рандомізованого рядка, а інший для обчислення числа.

let maybeBig = Math.random() > .5 ? 'big' : 'small';

let vdom = <p class={maybeBig}>Hello {40 + 2}!</p>;
                 // ^---JS---^       ^--JS--^
Увійти у повноекранний режим Вихід із повноекранного режиму

Якщо виконати render(vdom, document.body), з'явиться текст "Hello 42!".

А тепер це ж саме але з HTM

HTM є альтернативою JSX, яка використовує стандартні шаблони з тегами JavaScript, усуваючи потребу в компіляторі. Якщо ви не стикалися з шаблонами з тегами, це особливий тип String literal, який може містити ${expression} поля:

let str = `Quantity: ${40 + 2} units`;  // "Quantity: 42 units"
Увійти у повноекранний режим Вихід із повноекранного режиму

HTM використовує ${expression} замість {expression} синтаксису з JSX, що може зробити зрозумілішим, які частини вашого коду є елементами HTM/JSX, а які — простим JavaScript:

import { html } from 'htm/preact';

let maybeBig = Math.random() > .5 ? 'big' : 'small';

let vdom = html`<p class=${maybeBig}>Hello ${40 + 2}!</p>`;
                        // ^--JS--^       ^-JS-^
Увійти у повноекранний режим Вихід із повноекранного режиму

Усі ці приклади дають однаковий результат: віртуальне дерево DOM, яке можна надати Preact для створення або оновлення існуючого дерева DOM.

Компоненти

Пізніше ми детальніше розповімо про компоненти, але наразі важливо знати, що такі елементи HTML, як <p> один із двох типів елементів віртуальної DOM. Інший тип — це Component, який є елементом Virtual DOM, де типом є функція, а не рядок, як p.

Компоненти є будівельними блоками додатків Virtual DOM. Наразі ми створимо дуже простий компонент, перемістивши наш JSX у функцію, яка буде відтворена для нас, тому нам більше не потрібно буде писати останній render() рядок:

import { createElement } from 'preact';

export default function App() {
    return (
        <p class="big">Hello World!</p>
    )
}
Увійти у повноекранний режим Вихід із повноекранного режиму

Спробуйте

Ви можете відредагувати код в оригіналі уроку і побачити, як ваші зміни впливають на результат.

Щоб перевірити те, чого ви навчилися в цьому розділі, спробуйте додати тексту ще більше шикарності! Зробіть слово World виділеним, обернувши його тегами HTML: <em> і </em>.

Потім зробіть весь текст фіолетовим, додавши властивість стилю. Опис стилю є спеціальним і дозволяє встановити значення об’єкта з однією або кількома властивостями CSS для елемента. Щоб передати об’єкт як значення властивості, вам потрібно буде використати {expression}, наприклад style={{ property: 'value' }}.

Результат

import { createElement } from 'preact';

export default function App() {
  return (
    <p class="big" style={{ color: 'purple' }}>
      Hello <em>World</em>!
    </p>
  )
}
Увійти у повноекранний режим Вихід із повноекранного режиму

Корисні матеріали

Найновіші коментарі (0)