Сьогодні мова піде про чергову JavaScript-бібліотеку, яка призначена для розробки інтерфейсів. Виникає таке відчуття, що такі бібліотеки з'являються все частіше і частіше. У цьому матеріалі ми розглянемо бібліотеку Moon.js і розкриємо її особливості, про які потрібно знати для того щоб приступити до роботи. Зокрема, ми поговоримо про те, як створювати нові Moon.js-проєкти, про те, як створювати елементи інтерфейсів, як обробляти події. Освоївши це керівництво, ви зможете користуватися Moon.js для розробки власних застосунків.
Бібліотека Moon.js
Moon.js - це мінімалістична JavaScript-бібліотека, призначена для розробки швидких і функціональних інтерфейсів. Вона має порівняно невеликі розміри, що дозволяє створювати на її основі досить компактні програми. Бібліотека відрізняється дуже високою продуктивністю. В Moon.js використовується підхід до проєктування інтерфейсів, заснований на компонентах. Для створення компонентів застосовуються шаблони. Ця бібліотека вельми схожа на Vue.js.
Сильні сторони Moon.js
- Moon.js відрізняється компактними розмірами (в мініфіцірованном і стислому вигляді це - близько 2 Кб). Це менше, ніж розміри інших бібліотек і фреймворків на кшталт React і Angular.
- Ця бібліотека відрізняється високою швидкістю рендеринга інтерфейсів.
- Moon.js - це бібліотека, заснована на функціональних методах розробки. При роботі з нею використовується підхід до проєктування інтерфейсів, заснований на так званих «драйверах».
Початок роботи
Бібліотеку Moon.js можна включити в проект двома способами. Перший полягає в установці її з NPM. Другий - в її підключенні безпосередньо на сторінку, на якій її планується використовувати. Якщо вирішено скористатися NPM-варіантом бібліотеки, то спочатку потрібно буде встановити пакет moon-cli, інструмент командного рядка:
$ npm i moon-cli -g
В даному прикладі цей інструмент встановлюється глобально, викликати його можна з будь-якої директорії. Для створення проєкту, заснованому на Moon.js, можна виконати наступну команду:
$ moon create moon-prj
Ця команда створює новий проєкт в каталозі moon-prj
. Після того, як буде завершено створення проєкту, в вашому розпорядженні буде основа майбутнього програми. Другий варіант використання Moon.js передбачає її підключення до сторінки, на якій її планується використовувати. У бібліотеки є модуль moon-browser
, який дозволяє користуватися її можливостями безпосередньо на сторінці, до якої вона підключена. Отже, для підключення бібліотеки до сторінці нам потрібно включити до складу сторінки два наступних тега:
<script src="https://unpkg.com/moon"></script> <script src="https://unpkg.com/moon-browser"></script>
Як бачите, відповідні скрипти завантажуються з CDN unpkg. У першому тезі імпортується основна бібліотека. У другому - бібліотека moon-browser
. Вона відповідає за компіляцію шаблонів Moon.js, за приведення їх до вигляду, придатного для виведення браузером. Тепер, для того щоб скористатися синтаксичними конструкціями Moon.js на сторінці, потрібно буде включити їх в тег <script>
, не забувши поставити його атрибут typeяк text/moon
.
<!-- Підключення до сторінки зовнішнього скрипта --> <script src="./main-script.js" type="text/moon"></script> <!-- Або код на самій сторінці --> <script type="text/moon"> ... </script>
Підключення Moon.js
Moon.js, як і інші бібліотеки та фреймворки, які використовуються для створення односторінкових застосунків, підключається до певного елемента сторінки. Зазвичай роль контейнера для Moon.js-застосунку відіграє елемент <div>
:
<div id="root"></div>
Подібний елемент, який є кореневим елементом Moon.js-застосунку, розміщують в коді файлу index.html
, що представляє собою точку входу в проєкт. Для підключення Moon.js до цього елементу використовується драйвер view
(нижче ми поговоримо про драйвери докладніше):
Moon.use({ view: Moon.view.driver("#root") })
Дана конструкція повідомляє бібліотеці про те, що вона повинна підключити застосунок до елементу з ідентифікатором root. При необхідності вказати бібліотеці подібний елемент можна, скориставшись API браузера, призначеним для роботи з DOM:
Moon.use({ view: Moon.view.driver(document.getElementById("root")) })
Тепер поговоримо про те, як в Moon.js організована робота з даними, і про те, як за допомогою цієї бібліотеки створювати елементи інтерфейсів.
Синтаксис опису елементів інтерфейсу
Для опису Moon.js-інтерфейсів використовується мова програмування Moon View Language (MVL), яка була розроблена спеціально для вирішення даного завдання. Вона нагадує JSX. Ця мова застосовується для опису елементів і для налаштування їх взаємовідносин. Ось приклад:
<script type="text/moon"> function aView(data) { return ( <div>Hi from Moon</div> ) } </script>
Нескладно помітити те, що в цьому фрагменті Moon.js-коду, відповідального за формування елемента <div>
, використовуються синтаксичні структури, що нагадують HTML. Але ці структури використовуються в JavaScript-коді. Такий JavaScript-код браузер виконати не зможе, але це від нього і не потрібно, тому що Moon.js компілює подібні конструкції в звичайний JavaScript.
Робота з даними
У Moon.js для управління візуальними зображеннями елементів і для роботи з даними використовується концепція драйверів. Тут ми поглянемо на драйвер, що дозволяє працювати з даними, а в наступному розділі поговоримо про драйвер, призначений для роботи з елементами інтерфейсу. Драйвер, призначений для роботи з даними, відповідає за зберігання даних програми і дозволяє користуватися даними там, де вони потрібні. Іншими словами, цей драйвер зберігає глобальне стан застосунку. Задати початкові дані Moon.js-застосунку можна за допомогою API Moon.use
:
Moon.use({ data: Moon.data.driver })
Записувати нові дані в стану можна, повертаючи їх з відповідних функцій:
Moon.run(({ data }) => { console.log(data) // undefined return { data: "Nnamdi" } })
API Moon.run
відповідає за запуск програми. Коллбек, переданий цьому API, отримує посилання на глобальні дані в аргументі data
. Так як на момент виклику цієї функції в data
поки нічого немає, команда console.log
із цього прикладу виведе undefined
. Ми повертаємо з коллбека об'єкт, у якого є властивість data
зі значенням Nnamdi
. Цей об'єкт буде являти собою новий стан застосунку, даними якого зможуть скористатися будь-які інші функції, які звертаються до data
. Механізм роботи з даними в Moon.js ми розглянули. Тепер докладніше поговоримо про роботу з елементами інтерфейсу.
Робота з елементами інтерфейсу
У Moon.js є драйвер view
, який призначений для створення елементів і для монтування їх в DOM. Ми вже розглядали фрагмент коду, повторений нижче, в якому до елементу <div>
підключається базовий елемент Moon.js:
Moon.use({ view: Moon.view.driver("#root") })
Саме тут виконується монтування елемента. Тепер функції можуть повертати елементи, які здатні замінювати старі елементи. Їх можна представляти у вигляді об'єктів, що містять властивість view
, в яке записані відповідні дані. Бібліотека бере значення властивості view
які повертається функцією об'єкта і записує його в елемент, підключений до елементу з ідентифікатором root.
У Moon.js використовується концепція віртуального DOM і потужний алгоритм порівняння старої і нової версій інтерфейсу. Це дозволяє бібліотеці приймати рішення про те, коли потрібно оновлювати DOM, і про те, які саме частини DOM потребують оновлення.
function handleClick() { return {}; } Moon.run(() => ({ view: <button @click=handleClick>Click Me!</button> }));
Тут коллбек, що передається Moon.run
, виводить в DOM кнопку. Відбувається це через те, що функція повертає об'єкт з властивістю view
. Значення, призначене цій властивості, потрапляє в DOM. У кнопки є обробник події click
, представлений функцією handleClick
. Ця функція повертає порожній об'єкт, її виклик не призводить до внесення змін в DOM.
Створення елементів
Moon.js представляє розробнику великий набір допоміжних функцій, призначених для створення елементів інтерфейсів. В результаті виявляється, що елементи можна створювати, використовуючи не мову опису інтерфейсів Moon.js, а відповідні функції:
const { div, text, node, p } = Moon.view.m
Moon.js експортує функції, імена яких відповідають іменам створюваних з їх допомогою елементів. Так, функція div
дозволяє створювати елементи <div>
. Функція text
створює текстові вузли. Функція node
дозволяє створювати призначені для користувача елементи. Функція p
створює елементи <p>
. Як бачите, імена цих функцій ясно вказують на їх призначення.Створимо елемент <div>
:
const Div = div({});
Призначати елементам атрибути можна якщо передати відповідній функції об'єкт з властивостями:
const Div = div({ class: "DivClass" });
Тут ми описали елемент <div>
, в атрибут class
якого має бути записано значення DivClass
. Ось як створити текстовий елемент:
const Text = text({ data: "A text node" });
У властивості data
об'єкта, переданого функції text
, є текст для елемента. Створимо кастомний елемент:
const CustomEl = node("custom-el");
Для того щоб задати цьому елементу який-небудь атрибут, можна зробити так:
CustomEl({ "attr": "attr-value"})
Події
Підключати до елементів обробники подій можна, користуючись конструкцією, в якій застосовується символ @
:
function handleClick() { return {}; } Moon.run(() => ({ view: <button @click=handleClick>Click Me!</button> }));
В результаті на сторінку буде виведена кнопка з текстом Click Me
, після натискання на яку буде викликана функція handleClick
.
Компоненти
У Moon.js функції - це компоненти. Це означає, що функції можна згадувати в описі елементів інтерфейсу. Те, що повертає функція, буде включено до складу елемента. Припустимо, у нас є така функція:
function aView({ data }) { return <div>A View</div> }
Ця функція, aView
, повертає елемент, який може бути візуалізувати:
Moon.run(() => { view: <div><aView /></div> })
Ім'я функції в цьому прикладі використовується в ролі імені елемента. В результаті виконання цього коду виявиться, що те, що повертає функція, буде поміщено в тег <div>
. Коли все це потрапить в DOM, там виявиться така розмітка:
<div> <div>A View</div> </div>
Розробка застосунків, заснованих на Moon.js
Для того щоб зібрати воєдино все те, про що ми щойно говорили, давайте створимо на Moon.js простий TODO-застосунок. Тут ми скористаємося відповідним прикладом , який підготовлений розробниками Moon.js. Хочу нагадати про те, що рекомендується, освоюючи нові бібліотеки і фреймворки, створювати з їх допомогою невеликі застосунки. Це дозволяє прискорити навчання і допомагає зрозуміти особливості роботи досліджуваних інструментів. Спочатку мова йде про їх засади, але з часом приходить і розуміння складніших механізмів. Ось як виглядає сторінка цього застосунку.

На сторінці є заголовок, поле, кнопка, і список справ, який можна поповнювати, вводячи їх опис в поле і натискаючи на кнопку. Почнемо роботу зі створення файлу index.html
. Тут ми підключимо Moon.js безпосередньо на сторінку:
<html> <body> <div id="root"></div> </body> <script src="https://unpkg.com/moon"></script> <script src="https://unpkg.com/moon-browser"></script> <!-- Воспользуемся скриптом, встроенным в страницу --> <script type="text/moon"> function viewTodos({data, view}) { return ( <div> <input type="text" value=data.todo @input=updateTodo/> <button @click=createTodo>Create</button> <ul children=(data.todos.map(todo => <li>{todo}</li> ))/> </div> ) } function updateTodo({ data, view }) { const dataNew = { ...data, todo: view.target.value }; return { data: dataNew, view: <viewTodos data=dataNew/> } } function createTodo({ data }) { const dataNew = { todo: "", todos: [...data.todos, data.todo] }; return { data: dataNew, view: <viewTodos data=dataNew/> } } <!-- Настройка драйверов data и view --> Moon.use({ data: Moon.data.driver, view: Moon.view.driver("#root") }) <!-- Запуск приложения --> Moon.run(() => { data: [], view: <viewTodos data=[]> }) </script> </html>
Функція viewTodos
виводить елементи, необхідні для введення відомостей про нові справи і для виведення їх у вигляді списку. Її аргументами є data
та view
.
Функція createTodo
створює нову справу і повертає її у властивості data
.
Функція updateTodo
записує нову справу в стан застосунку. Зверніть увагу на обробники подій @click
та @input
, які є в функції viewTodos
. Подія @input
викликається при введенні тексту, що описує справу, в відповідне поле. При обробці цієї події викликається функція updateTodo
. Аргумент view
у цій функції представляє подію, що відбулася. Користуючись гею, ми звертаємося до DOM і отримуємо дані, введені в поле. Потім ці дані потрапляють в стан у вигляді властивості todo
.
Подія @click
викликається після натискання на кнопку. Вона виконує запис нової справи в список справ. Для вирішення цього завдання використовується функція createTodo
. Ця функція звертається до властивості стану todo
і записує нові дані у властивість todos
, у глобальні дані та повертає його із властивістю view
, встановленою для <viewTodos>
, представлений відповідною функцією, в атрибут data
якого записано значення dataNew
.
Це призведе до виконання повторного рендеринга viewTodos
і до оновлення DOM. У список справ, виведений на сторінці, буде додано нову справу. Запустіть цю програму в браузері і поекспериментуйте з нею.
Підсумки
Ми розібрали основи Moon.js. А саме, поговорили про те, що користуватися бібліотекою можна, встановлюючи її з NPM і підключаючи до сторінок безпосередньо. Далі, ми обговорили внутрішні механізми бібліотеки: роботу з даними, обробку подій, розробку компонентів.Мені здається, що Moon.js - це приємна бібліотека. І, якщо навіть не говорити про інші переваги, вона мені симпатична через компактний розмір.
Джерело: Introduction to Moon.js
Ще немає коментарів