Практические примеры. Живые демонстрации.
Выберите пример, чтобы открыть его на весь экран с предпросмотром и исходным кодом рядом.
Основы
4Приёмы, из которых состоит каждое приложение Nuclo.
Счётчик
Измените состояние, затем вызовите update(). Динамический текст обновится.
Список задач
Используйте list() для повторяющихся элементов. После каждого изменения вызывайте update().
Поисковый фильтр
Фильтруйте массив обычным JavaScript и выводите результаты с помощью list().
Стили
Создавайте классы через css(). Для небольших условных изменений используйте cx().
Компоненты
4Обычные функции со статическими и динамическими параметрами, дочерними узлами, списками с сопоставлением по идентичности объектов и вложенными данными. Каждый предпросмотр считает монтирования.
Статические и динамические параметры
Параметр-значение читается один раз при создании компонента. Параметр-функция читается при каждом update(). Сам компонент в обоих случаях выполняется один раз, что подтверждает счётчик монтирований.
Дочерние узлы и модификаторы
Компонент передаёт дочерние элементы через spread: построители, текст, объекты атрибутов и модификаторы. Условные части помещены в when(), поэтому окружающий их компонент не пересоздаётся.
Идентичность в списке
list() сохраняет строку, пока её объект находится в массиве: меняйте порядок, вставляйте и переименовывайте без потери ввода и фокуса. Переключатель клонирует объекты при каждом обновлении, показывая цену потери идентичности.
Вложенные данные
Команда с участниками и задачами: один компонент на уровень, вложенные вызовы list(), производные счётчики как функции тех же объектов. Глубокое изменение затрагивает только соответствующие узлы.
API
13Небольшая демонстрация каждого строительного блока — та же, что встроена в документацию.
Функции построения элементов
Построитель принимает атрибуты, статические дочерние узлы и динамический текст. Rename меняет состояние, затем вызывает update().
Компоненты
Компонент — обычная функция. Каждый вызов Counter() хранит собственный счётчик.
Атрибуты
Значения атрибутов могут быть функциями. Вторая кнопка переключает busy и вызывает update(); атрибуты disabled и aria-busy кнопки Save следуют за этим значением.
События
onInput и onKeyDown — обычные атрибуты. Введите текст, затем нажмите Escape, чтобы очистить поле.
Жизненный цикл
onMount запускает интервал и возвращает функцию очистки. При размонтировании она выполняется, поэтому счётчик останавливается до следующего монтирования таймера.
Явные обновления
count++ меняет только переменную. Текст обновится при следующем update(), вызванном этой кнопкой или другим действием на странице.
Динамические значения
Измените имя. Статический текст зафиксирован при создании элемента; динамический вычисляется при каждом update(). forceUpdate() заново строит дерево, поэтому обновляется и статический текст.
update()
Каждый update() вычисляет все динамические значения, даже если их данные не изменились. Другие демонстрации на странице тоже увеличивают счётчик.
scope()
Обе кнопки добавляют элемент и переименовывают пользователя. update('cart') обновляет только панель в указанной области.
when()
Выбирается первое истинное условие; иначе выводится .else(). Новая ветвь создаётся с нуля.
list()
Строки сопоставляются по идентичности объектов. Отметьте строку и нажмите Reverse: тот же <li> переместится вместе с флажком.
region() и into()
Макет с основным регионом со стеком представлений и боковым регионом заполняется снаружи. Введите текст в Home, откройте и закройте диалог: текст сохранится. Article заполняет оба региона одним into().
forceUpdate()
update() обновляет только динамическую строку lang. forceUpdate() повторно вызывает App и изменяет тот же <h1>. Явная форма перестраивает только это дерево, а не всю страницу.
Стили
3Создавайте классы, объединяйте их и используйте небольшую тему.
Формы
3Проверка обычными функциями над обычным состоянием, затронутые поля, шаги и динамические строки.
Валидация полей
Правила — обычные функции над обычным состоянием. Ошибки появляются после взаимодействия с полем. Асинхронная проверка с debounce показывает состояние ожидания, а отправка формы дожидается завершения всех проверок.
Многошаговая форма
Три шага — ветви when() с одним объектом данных. Next отмечает поля шага как затронутые и переходит дальше только после успешной валидации. На последнем шаге все данные показаны со ссылками «Редактировать».
Динамические строки
Позиции счета в массиве выводятся через list(). Каждая строка проверяет свои данные, итог учитывает только корректные строки, а введенные значения сохраняются при добавлении и удалении других строк.
SVG
27Графики, анимации, инструменты и игры из построителей SVG, управляемые обычными данными, событиями указателя и update().
Столбчатая диаграмма
Прямоугольники строятся из массива. Их y и height вычисляются из данных, поэтому update() перемещает столбцы.
Линейный график
Путь, d которого построен из точек, с областью градиента и одним кругом на точку.
Кольцевая диаграмма
Каждому сектору соответствует окружность. stroke-dasharray задает его долю кольца, а stroke-dashoffset — начальную позицию.
SVG-анимация
SMIL через функции построения элементов: animateSvg заставляет солнце пульсировать, а animateTransformSvg вращает планету по орбите. Динамический dur задает скорость.
Стрелочный индикатор
Дуга заполняется с помощью stroke-dashoffset, а стрелка поворачивается через CSS transform. Оба значения зависят от одного числа.
Радарная диаграмма
Пять значений по пяти осям. Форма представляет собой один путь, d которого вычисляется на основе данных, поэтому update() преобразует его.
Тепловая карта
Сетка прямоугольников, у которых fill-opacity зависит от уровня. Нажмите на ячейку, чтобы повысить его. Дочерний titleSvg задает всплывающую подсказку.
Подсказка при наведении
События указателя на элементах SVG. onPointerEnter выбирает активную точку, и к ней перемещается группа подсказок.
Редактор кривых
Перетаскивайте контрольные точки кубической кривой Безье. onPointerDown выбирает точку, onPointerMove на svg перемещает ее, и кривая меняется вместе с ней.
Часы
Стрелки — линии, у которых transform вычисляется из времени. onMount запускает таймер и возвращает функцию очистки.
Переключение значков
Значок меню, который превращается в крест с переходами CSS, и сердце, которое пульсирует с помощью SMIL-анимации по щелчку.
Данные в реальном времени
Два ряда данных сдвигаются влево по таймеру. CSS-переход длительностью в один такт делает движение плавным, а наведение показывает значение любой точки.
Свечной график
Сорок ячеек читают данные своих свечей. Меняйте таймфрейм, включайте среднюю линию, смотрите значения при наведении или наблюдайте за обновлением текущей свечи.
Гонка гистограмм
Десять полос никогда не покидают DOM. Их ранг устанавливает translateY, поэтому переход перемещает каждый из них в свою строку при изменении значений.
Диаграмма с областями с накоплением
Четыре полосы переключаются между составной, потоковой и процентной раскладкой. Скрытие серии дает только нулевую толщину ее полосы, поэтому структура команд каждого пути остается прежней.
Древовидная карта
Древовидная карта с прямоугольниками близких пропорций и переходом к деталям. При смене показателя ячейки перемещаются в новые прямоугольники, а нажатие на группу показывает ее дочерние элементы.
Гистограмма в реальном времени
Данные поступают из четырех распределений. Число значений в интервалах пересчитывается при каждом изменении, аппроксимирующая колоколообразная кривая следует за средним, а ползунок задает количество интервалов.
Поле для рисования
События указателя рисуют ломаные линии. list() выводит по одной линии на штрих, а текущий штрих удлиняется при каждом update().
Поворотный регулятор
Собственный ползунок: угол указателя задает значение, клавиши со стрелками меняют его пошагово, а pathLength="100" позволяет представить значение длиной штриха.
Цветовое колесо
Выберите оттенок по углу и насыщенность по расстоянию. Колесо состоит из девяноста клиньев, радиального градиента и темного диска.
Спирограф
Колесо катится внутри кольца, а перо рисует его траекторию. Каждый кадр удлиняет один штрих и обновляет только свой scope().
Прыгающие мячи
Гравитация, стены и столкновения в цикле requestAnimationFrame. Оттяните и отпустите, чтобы запустить мяч.
Сливающиеся капли
Размытие и фильтр цветовой матрицы заставляют капли сливаться. След из окружностей движется за указателем.
Граф с силовой раскладкой
Узлы отталкиваются, связи притягивают, а движение постепенно затухает. Перетащите узел или нажмите на него, чтобы добавить дочерний.
Выделение и масштабирование
Выделите диапазон на обзорном графике, чтобы увеличить соответствующий участок графика выше. clipPath следует за выделением и задает его цвет.
Крестики-нолики
Играйте против компьютера. when() добавляет каждый знак, а CSS-анимация штриха постепенно прорисовывает его.
Текст по кругу
Введите текст эмблемы. textPath располагает его по окружности, а textLength растягивает ровно на один оборот.
Маршрутизация
6Таблицы маршрутов, сопоставление, активный маршрут, слои и загрузчики. nuclo-router — отдельный пакет: npm install nuclo nuclo-router.
Приложение с маршрутизацией
Настоящее приложение с собственным маршрутизатором, работающее в фрейме: таблица маршрутов, один outlet(), простые ссылки, состояние ожидания и ошибка 404. Перейдите по ссылкам, затем нажмите «Назад».
Вложенные маршруты
Docs — макет с дочерними маршрутами. Тема отображается в его outlet(), а ссылки ./topic разрешаются относительно маршрута макета. Введите заметки и переключите тему: макет не перестраивается.
Загрузчики данных маршрутов
Страница публикации экспортирует load(), который выполняется до ее построения. Наблюдайте за router.pending во время ожидания и за состоянием ошибки с Retry, когда загрузчик выбрасывает исключение для проблемной публикации.
Слои
Форма заказа открывает страницу клиента отдельным слоем и ждет результата. Форма не перестраивается, поэтому заметки сохраняются. Save завершает push с результатом, а Cancel и «Назад» закрывают слой без результата.
Несколько маршрутизаторов и загрузка
Два маршрутизатора, два индикатора загрузки. У макета магазина и его раздела есть load(): они выполняются параллельно с общим router.pending. У боковой панели — собственный маршрутизатор, созданный, но не запущенный, и собственный флаг загрузки, обновляемый из onNavigate.
Сопоставление с образцом
Статические шаблоны, :param и *rest, а также таблица разделов, смонтированная под двумя родительскими элементами. Введите путь и посмотрите match(), который разрешается без загрузки чего-либо.
Приложения
15Большие программы на весь экран с настоящим исходным кодом во вкладках: рабочий стол с окнами, таблица данных, чат, игры, редакторы и библиотеки с собственным состоянием.
Конструктор страниц
Пишите прямо на странице, перетаскивайте блоки за маркеры, чтобы менять порядок или перемещать их в макеты. Нажмите / для вставки или правую кнопку мыши для меню действий. Настраивайте grid- и flex-макеты, отменяйте правки, проверяйте вид на телефоне и экспортируйте HTML.
Пошаговая сортировка
Движок — обычный JavaScript: генераторы изменяют массив и приостанавливаются после каждого шага. Проигрыватель вызывает next() и update(). Столбцы — list() одних и тех же объектов, поэтому перестановка перемещает два элемента.
Канбан-доска
Доска команды: добавляйте задачи, назначайте их людям, редактируйте их в диалоговом окне, фильтруйте по человеку или осуществляйте поиск, перетаскивайте их между столбцами и отменяйте удаление. Столбцы и карточки представляют собой простые массивы одних и тех же объектов; каждое перемещение — это splice(). Строки сопоставляются по идентичности объектов, поэтому при перетаскивании, сортировке, назначении или редактировании карточки повторно используется ее элемент. Количество монтирований на экране доказывает это.
Инспектор three.js
Библиотека, владеющая собственным состоянием. Панель считывает позиции, цвета и флаги прямо из объектов three.js и записывает в них изменения. Цикл рендеринга вызывает update() один раз для каждого кадра; состояние нигде не дублируется.
Бесконечная прокрутка
Бесконечная лента: быстрая имитация fetch() генерирует страницы на лету в один обычный массив. В DOM находятся только строки рядом с видимой областью: list() выводит posts.slice(start, end) между двумя распорками, поэтому страница остается легкой даже при ста тысячах публикаций. Элемент-маркер в конце ленты запрашивает следующую страницу еще до появления в поле зрения.
Рабочий стол
Рабочий стол с файлами, заметками, терминалом, калькулятором, таймером, канбан-доской, финансами и календарем. Создавайте папки, редактируйте заметки и выполняйте команды оболочки на общем виртуальном диске, сохраненном в браузере. Вводите числа в калькулятор с клавиатуры, нажимайте в любом месте терминала для фокуса на строке ввода, перетаскивайте карточки между столбцами или ведите учет в таблице «Финансы» с обновляемыми графиками — данные хранятся в IndexedDB. Окна сохраняют состояние при перемещении, изменении размера и переключении приложений. Работающий таймер выводит содержимое в область уведомлений панели задач через into().
Граф вычислений
Соединяйте числа, текст и переключатели через узлы вычислений, сравнений и If: значения обновляются при вводе. Функции тоже заданы графами: их узлы Input и Output служат портами каждого Call. Вызов может ссылаться на свою функцию, поэтому факториал и сумма используют рекурсию с выходом через If. Движок написан на обычном JavaScript: каждый узел — генератор, который приостанавливается для запроса входных данных, а один цикл управляет ими через собственный стек. Поэтому sum(50000) создает пятьдесят тысяч вложенных вызовов примерно за десятую долю секунды, не затрагивая стек вызовов JavaScript. Рекурсию без выхода останавливает только лимит шагов. Перетаскивание меняет x и y и обновляет лишь область холста. Счетчик запусков показывает, что перемещение не запускает вычисления графа.
Сетка данных
Рабочая таблица, содержащая более 10 000 простых объектов-строк. Поиск, фильтрация, сортировка и разбиение по страницам — это простые функции для массива, а тело таблицы — это list() для текущей страницы. Строки сопоставляются по идентичности объектов, поэтому при сортировке перемещаются строки, которые остаются на странице, и отредактированная строка везде является одним и тем же объектом. Подсчет построенных строк доказывает это.
Чат
Чат с тремя каналами. Каждый канал — обычный объект с историей, курсором, состоянием набора текста, черновиком и позицией прокрутки. При переключении все это сохраняется, а update("chat-sidebar") обновляет только счетчики непрочитанных сообщений. История подгружается вверх через unshift(), и scrollTop увеличивается на высоту добавленного содержимого. Сообщение видно до получения сервером, send() обновляет тот же объект, а повторная отправка, редактирование, удаление и реакции не перестраивают строку. В сообщениях поддерживаются код, полужирный текст, ссылки и @упоминания.
Панель данных в реальном времени
Карточки обновляются с разной частотой: от двадцати до одного раза в секунду. Каждая карточка — scope(), а ее таймер вызывает update() с ее идентификатором, поэтому один такт пересчитывает только эту карточку. Счетчики показывают число вычислений динамических значений: переключитесь на обычный update(), и часы будут пересчитываться около ста раз в секунду ради одного изменения.
Пиксельный редактор
Изображение — обычный массив из 1024 строк с цветами. Каждая ячейка читает из него свой цвет. Штрих меняет массив и вызывает update(), а при завершении редактор сохраняет копию через slice(). Отмена, повтор и любой шаг истории в list() возвращают прежний массив: без хранилища и неизменяемых данных.
Змейка
Игровой цикл — таймер: он вызывает step() для обычных объектов и затем update() один раз за такт. Змейка — list() объектов клеток. На каждом такте объект хвоста становится новой головой, поэтому один элемент перемещается, а новые не создаются. Счетчик созданных сегментов растет только после еды. Еда появляется с анимацией keyframes().
Шаговый секвенсор
Библиотека с собственным отсчетом времени. Web Audio заранее планирует каждую ноту на своей временной шкале. Паттерн — обычный двумерный массив логических значений: сетка переключает их, а планировщик читает, поэтому изменение слышно на следующем проходе. Указатель воспроизведения обновляет только свой scope() при смене звучащего шага. Звук запускается при первом Play, а функция очистки onMount закрывает аудиоконтекст: при выходе из примера звук останавливается.
Переключатель языка
Каждая надпись — статическое значение, как в одноязычном приложении, поэтому update() не читает ее повторно: действия в корзине обновляют только количество и итоговую сумму. Переключение языка вызывает forceUpdate() для этого дерева: компонент выполняется снова и обновляет те же элементы, включая lang и dir. Валюты, формы множественного числа, даты и списки форматируются через Intl. Корзина и введенный промокод сохраняются.
Редактор темы
Небольшая библиотека компонентов: createCss() задает имена токенам, а variants() создает на их основе кнопки, значки, карточки, поля ввода, уведомления и переключатели. Токены — переменные CSS, поэтому каждый класс компилируется один раз. Элементы управления меняют обычный объект темы и вызывают update(), который перезаписывает текст одного элемента style.