Почти — потому что используется всего две функции из библиотеки:
-
Создать
элемент DOM -
Обновить
элемент DOM
Эта библиотека упрощает использование нативных функций DOM, таких как createElement
и replaceChild
. Библиотека Fusor направлена на то, чтобы сделать эти функции проще и компактнее.
Ниже приведены примеры распространенных проблем. Попробуйте воспроизвести их с использованием инструментов, которые вы сейчас используете. Вы можете быть удивлены, обнаружив, что разработка с Fusor может быть наиболее компактным, гибким, легким и производительным способом создания фронтенд-приложений.
Оглавление
Установка
npm install @fusorjs/dom
Или:
-
JSX стартовый проект для: JavaScript или TypeScript
-
CDN: https://esm.sh/@fusorjs/dom или https://cdn.skypack.dev/@fusorjs/dom
Создание и Обновление DOM
import {getElement, update} from '@fusorjs/dom'; import {section, div} from '@fusorjs/dom/html'; let count = 0; const block = section( {class: () => (count % 2 ? 'odd' : 'even')}, div('Seconds ', () => count, ' elapsed'), div('Minutes ', () => Math.floor(count / 60), ' elapsed'), ); document.body.append(getElement(block)); setInterval(() => { count++; update(block); }, 1000);
Только крохотные части у block
дерева DOM обновляются, если они отличаются от текущих значений.
Поддержка JSX
import {getElement, update} from '@fusorjs/dom'; let count = 0; const block = ( <section class={() => (count % 2 ? 'odd' : 'even')}> <div>Seconds {() => count} elapsed</div> <div>Minutes {() => Math.floor(count / 60)} elapsed</div> </section> ); document.body.append(getElement(block)); setInterval(() => { count++; update(block); }, 1000);
Синтаксис Установки Параметров
import {getElement, update} from '@fusorjs/dom'; import {section} from '@fusorjs/dom/html'; let count = 0; const block = section( { id: 'set attribute or property automatically', title_a: 'set attribute', style_p: 'set property', focus_e: () => 'set bubbling event handler', blur_e_capture_once: () => 'set capturing event handler once', // update dynamic values in this DOM node: click_e_update: () => count++, // same as click_e: () => {count++; update(block);}, // same as click_e: (event, self) => {count++; update(self);}, class: count % 2 ? 'odd' : 'even', // static class: () => (count % 2 ? 'odd' : 'even'), // dynamic }, 'Static child ', count, ' never changes.', 'Dynamic child ', () => count, ' is wrapped in a function.', ); document.body.append(getElement(block));
Компонент с Состоянием
import {getElement} from '@fusorjs/dom'; import {button, div} from '@fusorjs/dom/html'; const ClickCounter = (count = 0) => button({click_e_update: () => count++}, 'Clicked ', () => count, ' times'); const App = () => div(ClickCounter(), ClickCounter(22), ClickCounter(333)); document.body.append(getElement(App()));
Версия JSX
import {getElement} from '@fusorjs/dom'; const ClickCounter = ({count = 0}) => ( <button click_e_update={() => count++}>Clicked {() => count} times</button> ); const App = () => ( <div> <ClickCounter /> <ClickCounter count={22} /> <ClickCounter count={333} /> </div> ); document.body.append(getElement(<App />));
Компоненты в обеих версиях совместимы.
Тот же Компонент Разными Способами
import {button} from '@fusorjs/dom/html'; const ClickCounter = (count = 0) => { const self = button( {click_e: () => {count++; update(self);}}, 'Clicked ', () => count, ' times', ); return self; }; const ClickCounter = (count = 0) => button( {click_e: (event, self) => {count++; update(self);}}, 'Clicked ', () => count, ' times', ); const ClickCounter = (count = 0) => button( {click_e_update: () => count++}, 'Clicked ', () => count, ' times', );
Контролируемый Компонент Ввода
Или Controlled Input в терминах React.
import {getElement} from '@fusorjs/dom'; import {input, div} from '@fusorjs/dom/html'; const UppercaseInput = (value = '') => input({ value: () => value.toUpperCase(), input_e_update: (event) => (value = event.target.value), }); document.body.append( getElement( div(UppercaseInput(), UppercaseInput('two'), UppercaseInput('three')), ), );
Точное Обновление DOM
import {getElement, update} from '@fusorjs/dom'; import {section, div} from '@fusorjs/dom/html'; let count = 0; const seconds = div('Seconds ', () => count, ' elapsed'); const block = section( seconds, div('Minutes ', () => Math.floor(count / 60), ' elapsed'), ); document.body.append(getElement(block)); setInterval(() => { count++; update(seconds); // not minutes }, 1000);
Это обновит только секунды, а не минуты.
Остановка Рекурсии Обновления
import {getElement, update} from '@fusorjs/dom'; import {section, div} from '@fusorjs/dom/html'; let count = 0; const seconds = div('Seconds ', () => count, ' elapsed'); const block = section( () => seconds, // wrapped in a function to escape div('Minutes ', () => Math.floor(count / 60), ' elapsed'), ); document.body.append(getElement(block)); setInterval(() => { count++; update(block); }, 1000);
Это обновит только минуты, но не секунды.
Только компоненты (seconds
, block
) обновляются рекурсивно. () => seconds
— это функция, а не компонент.
Каждая функция из @fusorjs/dom/html
возвращает компонент, если он содержит динамические значения. То же самое относится и к определениям JSX.
Жизненный Цикл Компонента
-
Создать компонент
-
Подключить к DOM
-
Обновить DOM
-
Отключить от DOM
import {getElement, update} from '@fusorjs/dom'; import {div} from '@fusorjs/dom/html'; const IntervalCounter = (count = 0) => { console.log('1. Create component'); return div( { mount: (self) => { console.log('2. Connect to DOM'); const timerId = setInterval(() => { count++; update(self); console.log('3. Update DOM'); }, 1000); const unmount = () => { clearInterval(timerId); console.log('4. Disconnect from DOM'); }; return unmount; }, }, 'Since mounted ', () => count, ` seconds elapsed`, ); }; const instance = IntervalCounter(); // 1. Create component const element = getElement(instance); document.body.append(element); // 2. Connect to DOM setTimeout(() => element.remove(), 15000); // 4. Disconnect from DOM
Автоматическое/Реактивное Обновление
Автоматические/реактивные обновления в больших фреймворках — это не что иное, как реализация паттерна Observable. Это включает в себя State в React, Signals в Solid, Redux, MobX и многие другие. В Fusor вы можете использовать любую из этих библиотек.
Здесь мы обсуждаем универсальное решение:
Библиотека Роутинга
import {update} from '@fusorjs/dom'; import {Observable} from 'Any/Observable/Signal/Redux/Mobx...'; // Modern routing handling const observable = new Observable(); const read = () => location.hash.substring(1); // omit "#" let route = read(); window.addEventListener( 'popstate', () => { const next = read(); if (route === next) return; route = next; observable.notify(); }, false, ); // Fusor integration export const getRoute = () => route; export const mountRoute = (self) => { const callback = () => update(self); observable.subscribe(callback); return () => observable.unsubscribe(callback); };
Реактивный Компонент
Переключение компонентов, когда выбран текущий маршрут.
import {span, a} from '@fusorjs/dom/html'; import {getRoute, mountRoute} from './router'; export const RouteLink = (title, route) => span({mount: mountRoute}, () => getRoute() === route ? title // when selected : a({href: `#${route}`}, title), );
Динамическое Создание и Обновление DOM
import {getElement} from '@fusorjs/dom'; import {ul, li} from '@fusorjs/dom/html'; import {RouteLink} from './RouteLink'; const block = ul( [...Array(10)].map((v, i) => li(RouteLink(`${i + 1}. Section`, `url-to-${i + 1}-section`)), ), ); document.body.append(getElement(block));
Кеширование и Мемоизация
Тяжелый компонент создается только один раз.
import {div, br} from '@fusorjs/dom/html'; let isVisible = true; // can change const block = div( ( (cache = HeavyComponent()) => () => isVisible && cache )(), br(), () => RecreatedEveryUpdate(), );
Обработка Исключений
import {section, p} from '@fusorjs/dom/html'; const Value = (value) => { if (value === undefined) throw new Error(`provide a value`); return p(value); }; const block = section( p('Before'), (() => { try { return [ Value(1), Value(), // will throw Value(3), ]; } catch (error) { if (error instanceof Error) return p('Exception: ', error.message); return p('Exception: unknown'); } })(), p('After'), );
Заключение
Теперь вы знаете все, что нужно для начала разработки современных фронтенд-приложений с Fusor.
Насколько мне известно, разработка с Fusor — это самый лаконичный, гибкий, легковесный и производительный способ создания фронтенд-приложений.
ссылка на оригинал статьи https://habr.com/ru/articles/897454/
Добавить комментарий