Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mini Framework

A small vanilla JavaScript framework with:

  • A virtual DOM abstraction
  • A tiny renderer + diff algorithm
  • A global store (shared state)
  • A hash-based router
  • A simple event system using on handlers in virtual nodes

The goal is clarity over complexity.

How It Works

The framework has five core parts:

  1. Virtual DOM helpers (src/virtual-dom-helpers.js)

    • createElement(tagName, props, children) creates an element node
    • createFragment(children) groups nodes without adding extra DOM wrappers
    • createTextNode(value) creates text nodes
  2. Renderer (src/mount-dom.js, src/diff-algorithm.js, src/destroy-dom.js)

    • mountDOM creates real DOM from virtual nodes
    • patchDOM updates existing DOM by comparing old/new virtual nodes
    • destroyDOM removes nodes and event handlers
  3. Event handling (src/dom-events.js)

    • User code defines events in virtual node props.on
    • Example: on: { click() { ... } }
    • Framework attaches and removes handlers internally
  4. State management (src/state.js)

    • createStore(initialState, reducers) creates global shared state
    • dispatch(actionName, payload) updates state through reducers
    • subscribe(listener) lets app re-render on state changes
  5. Routing (src/router.js)

    • createRouter({ defaultPath }) manages URL hash routes (#/, #/active)
    • navigate(path) changes route
    • subscribe(listener) notifies on route change

Clean Public API

All main APIs are exported from src/framework.js:

import {
  createElement,
  createFragment,
  createTextNode,
  createStore,
  createRouter,
  createApp,
} from './src/framework.js';

Create Elements

const titleNode = createElement('h1', { class: 'title' }, ['Hello']);

const buttonNode = createElement('button', {
  class: 'primary',
  on: {
    click() {
      console.log('Clicked');
    },
  },
}, ['Click me']);

const pageNode = createFragment([titleNode, buttonNode]);

Add Events

Events are defined in props.on.

createElement('input', {
  value: 'text',
  on: {
    input(event) {
      console.log(event.target.value);
    },
    keypress(event) {
      if (event.key === 'Enter') {
        console.log('Submit');
      }
    },
  },
});

You never call addEventListener directly in app UI code.

State Management

const initialState = { count: 0 };

const reducers = {
  increment(state) {
    return { ...state, count: state.count + 1 };
  },
  setCount(state, value) {
    return { ...state, count: value };
  },
};

const store = createStore(initialState, reducers);

store.subscribe((nextState, actionName) => {
  console.log('Action:', actionName, 'State:', nextState);
});

store.dispatch('increment');
store.dispatch('setCount', 5);

Routing

const router = createRouter({ defaultPath: '/' });

router.subscribe((path) => {
  console.log('Route changed:', path);
});

router.start();
router.navigate('/about'); // URL becomes #/about

Routes are hash-based so it works with static hosting.

App Composition

const app = createApp({
  store,
  router,
  view({ state, route, emit, navigate }) {
    return createElement('div', {}, [
      createElement('h1', {}, [`Route: ${route}`]),
      createElement('button', {
        on: {
          click() {
            emit('increment');
          },
        },
      }, ['Increment']),
      createElement('button', {
        on: {
          click() {
            navigate('/about');
          },
        },
      }, ['Go to About']),
    ]);
  },
});

router.start();
app.mount(document.getElementById('root'));

Current Demo

The root todo-app.js includes a TodoMVC-style app that demonstrates:

  • Element creation with virtual nodes
  • Event handling via on
  • Shared state with reducers
  • Route-based filtering (#/, #/active, #/completed)

Suggested Folder Structure

Current structure is already small and clear. If the project grows, use this:

mini-framework/
  src/
    core/
      virtual-dom-helpers.js
      mount-dom.js
      diff-algorithm.js
      destroy-dom.js
      dom-attributes.js
      dom-events.js
    state/
      store.js
    router/
      router.js
    framework.js
  examples/
    todo-app.js
  index.html
  style.css
  todo-app.js
  README.md

Notes

  • No external framework is used.
  • Everything is vanilla JavaScript.
  • Keep reducers pure and return new state objects.
  • Keep view functions focused: read state/route and return virtual nodes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages