Найти в Дзене

Sinuous — JavaScript UI


Есть много библиотек и фреймворков, которые помогают преодолеть все препятствия на пути JavaScript разработчика. Если раньше мы использовали ванильный JS, то со временем пришёл jQuery, а затем React и Vue. Каждый год появляется все больше новых библиотек, фреймворков и инструментов. Некоторые из них продолжают развиваться и находят свою аудиторию, в то время как другие исчезают и постепенно забываются. В статье рассмотрим ещё одну библиотеку, которая может быть полезной для разработки небольших и простых пользовательских интерфейсов.

Что это вообще?
Sinuous — быстрая реактивная UI библиотека. Sinuous начинался как небольшой эксперимент, чтобы добиться такого же поведения, как Surplus , но с литералами шаблонов вместо JSX.
Размер Sinuous составляет всего 1.4kB. Это делает её идеальной для встраивания в HTML-страницу, компоненты или виджеты. Одна из целей — сохранить простоту Javascript. Поэтому в библиотеке очень мало специализированного синтаксиса. Если разрабатывается что-то действительно большое и сложное, несомненно стоит брать React/Vue.
Sinouse не использует VDOM в классическом смысле. Есть лишь map модуль, который делает что-то похожее. Для динамических частей Sinuous использует простой Observable , который обеспечивает обновления указанные в представлении. Иными словами, оцениваются лишь те части, которые изменяются, без необходимости сравнивать всё DOM-дерево.
Sinuous предоставляет template надстройку, которая может предварительно отображать повторяющиеся фрагменты HTML.
Вот ссылка на репозиторий Sinous на GitHub.
Установка
Sinuous доступен в NPM для использования с упаковщиком модулей или в приложении Node:

npm install sinuous
Простой компонент
Простой пример библиотеки, не требующий особых пояснений:

import { html } from 'sinuous';

const HelloMessage = ({ name }) => html`

 <!-- Prints Hello World -->

 <div>Hello ${name}</div>

`;

document.querySelector('.hello-example').append(

 html`<${HelloMessage} name=World />`

);
Единственное, что здесь следует отметить, что html тег скомпилирован для h вызова функций библиотекой HTM . Это можно сделать либо во время выполнения, либо во время сборки.
Компонент с сохранением состояния
Помимо получения входных данных через props, также поддерживается внутреннее состояние компонента, доступ к которому происходит через observables. При изменении данных состояния компонента, отображаемая разметка будет автоматически обновляться путём повторного вызова необходимых операций с DOM.

import { o, html } from 'sinuous';

const Timer = (props) => {

 const seconds = o(0);

 function tick() {

   seconds(seconds() + 1);

 }

 setInterval(tick, 1000);

 return html`

   <div>Seconds: ${seconds}</div>

 `;

};

document.querySelector('.counter-example').append(

 html`<${Timer}/>`

);
Простая тудушка
Функция o создаёт наблюдаемую переменную, которая может содержать любое значение, которое нужно сделать реактивным в представлении. Вызывая эту функцию без аргумента, она действует как метод получения значения; если передаётся аргумент, она устанавливает новое значение наблюдаемой переменной.
При первом рендеринге Sinuous обнаружит все использованные наблюдаемые переменные и выполнит соответствующие операции с DOM, сохранённые ранее. Если новому значению будет присвоена наблюдаемая переменная, она просто выполнит ранее сохранённые операции с DOM, используя новое значение.
import { o, html } from 'sinuous';

import { map } from 'sinuous/map';

const TodoApp = () => {

 let items = o([]);

 let text = o('');

 const view = html`

   <div>

   <h3>TODO</h3>

   <${TodoList} items=${items} />

   <form onsubmit=${handleSubmit}>

   <label htmlFor="new-todo">

   What needs to be done?

   </label>

   <input

   id="new-todo"

   onchange=${handleChange}

   value=${text}

   />

   <button>

   Add #${() => items().length + 1}

   </button>

   </form>

   </div>

 `;

 function handleSubmit(e) {

   e.preventDefault();

   if (!text().length) {

   return;

   }

   const newItem = {

   text: text(),

   id: Date.now
@
3 минуты