Skip to content
/ dom Public

Fusor is a simple JavaScript library that helps declaratively create and update DOM elements

License

Notifications You must be signed in to change notification settings

fusorjs/dom

Repository files navigation

Fusor

Fusor is a simple JavaScript library that helps to declaratively create and update DOM elements.

It is similar to React, but it operates at a lower level of abstraction. However, it is much simpler, more efficient, more flexible, and less verbose.

Key Features:

  • Simple ― two main API methods
  • Compliant ― follows W3C standards
  • Explicit/Flexible/Performant ― full control over: DOM creation/updates, state, context, diffing, concurrency
  • Small ― size ~3kB, no dependencies

Examples

>> TRY THEM LIVE <<

Reusable Component With Own State

import { getElement } from '@fusorjs/dom';

// This function runs once on creation, generating a DOM element
// and its updater function. On update, only its dynamic values
// are diffed and its DOM node is updated.
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 />));

Parameters And Children

import { update } from '@fusorjs/dom';

const divider = (
  <div
    name="set attribute or property automatically"
    name_a="set attribute"
    name_p="set property"
    name_e={() => 'set bubbling event handler'}
    name_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(divider);}} // same as
    click_e={(event, self) => {count++; update(self);}}

    // dynamic attribute or property is wrapped in a function
    class={() => (count % 2 ? 'odd' : 'even')}
  >
    Dynamic child {() => count} is wrapped in a function.
    Static child {count} never changes.
  </div>
);

Component Lifecycle

  1. Create component
  2. Connect to DOM
  3. Update DOM
  4. Disconnect from DOM
import { getElement, update } from '@fusorjs/dom';

const IntervalCounter = ({ count = 0 }) => (
  // 1. Create component
  <div
    mount={(self) => {
      // 2. Connect to DOM
      const timerId = setInterval(() => {
        count++;
        update(self); // 3. Update DOM
      }, 1000);

      return () => clearInterval(timerId); // 4. Disconnect from DOM
    }}
  >
    Since mounted {() => count} seconds elapsed
  </div>
);

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

Check SVG Analog Clock.

Documentation

Real-World Applications

  • TodoMvc - routing, global data store
  • Tutorial - nested routing, http request, lifecycle, custom element, caching, jsx, svg, mathml, xml

Start Coding

Start with a boilerplate project:

Or configure it manually

Contributing

Your suggestions and contributions are always welcome!

Please see CONTRIBUTING for details and CHANGELOG for agenda.