@killuakabani/create-my-framework
v1.0.57
Published
A simple framework for testing npx
Readme
SimpleJS Framework Documentation
Overview
SimpleJS is a lightweight JavaScript framework designed to simplify web development by abstracting the DOM, managing state, handling events, and supporting routing. With a diffing algorithm, it updates the DOM efficiently by comparing virtual DOM trees and modifying only what has changed, making it ideal for dynamic single-page applications (SPAs).
Features
- DOM Abstraction: Uses a virtual DOM to represent and manipulate UI elements.
- Efficient Updates: A diffing algorithm minimizes real DOM changes.
- Event Handling: Custom event system via attributes (e.g.,
onClick), with listener tracking for updates. - State Management: Centralized state that triggers UI updates.
- Routing: Path-based navigation for SPAs using browser history.
Getting Started
Setup
- Download the framework or clone it:
git clone https://github.com/Margoumachraf/framework.gitor
npx @killuakabani/create-my-framework my-app- Define your app logic in
/appand add routing in/app/index.js.
API Reference & Examples
Creating an Element
const div = SimpleJS.createElement('div', { class: 'container' }, ['Hello, World!']);- Purpose: Creates a virtual DOM node representing
<div class="container">Hello, World!</div>. - Parameters:
tag: The HTML tag (e.g.,'div','button').attrs: An object of attributes (e.g.,{ class: 'container' }). Required; use{}if no attributes.children: An array of child nodes (strings or virtual DOM objects). Optional; defaults to[].
Creating an Event
const button = SimpleJS.createElement('button', {
onClick: () => alert('Clicked!')
}, ['Click Me']);- Purpose: Attaches an event handler to the element, triggered on user interaction. Case-insensitive.
- How It Works: The
onClickattribute is detected during rendering or diffing, and the handler is bound to the real DOM element. Updates are managed efficiently.
Nesting Elements
const nested = SimpleJS.createElement('div', {}, [
SimpleJS.createElement('p', { class: 'text' }, ['Nested Text']),
'More Text'
]);- Purpose: Creates a
<div>with a<p>and a text node inside. - How It Works: Children can be virtual DOM nodes or strings, recursively rendered or updated.
Adding Attributes
const input = SimpleJS.createElement('input', {
type: 'text',
placeholder: 'Enter text',
class: 'input-field'
});- Purpose: Adds attributes like
typeorclassto an element. - How It Works: Attributes are applied during initial render and updated if changed in subsequent renders.
State Management
SimpleJS.state = {
count: SimpleJS.state.count || 0,
todos: [],
autoincrement: 1
};- Purpose: Updates the global state and triggers a re-render with diffing.
- Declaration: Define new states in the
stateobject inapp/index.js. Only global states are supported. - Accessing: Use
SimpleJS.state.countto read state. - Updating: Use
SimpleJS.setState()to update state. Examples:- Replace:
SimpleJS.setState({ count: 5 }); - Update based on previous value:
Both methods are equivalent; the first is more familiar to some developers.SimpleJS.setState((prev) => ({ count: prev.count + 1 })); // Recommended SimpleJS.setState({ count: SimpleJS.state.count + 1 });
- Replace:
Example with State
// in app/app.js
const App = () => SimpleJS.createElement('div', {}, [
`Count: ${SimpleJS.state.count || 0}`,
SimpleJS.createElement('button', {
onClick: () => SimpleJS.setState({ count: (SimpleJS.state.count || 0) + 1 })
}, ['Increment'])
]);Routing
SimpleJS.addRoute('/home', () => SimpleJS.createElement('h1', {}, ['Home']));
SimpleJS.router();- Purpose: Defines routes and renders components based on the current URL path (e.g.,
/home). Place routes inapp/index.js. - How It Works: Uses the browser’s
historyAPI to track navigation viawindow.location.pathname. If no route matches, aNotFoundcomponent is rendered. - Adding Routes:
SimpleJS.addRoute('/about', () => SimpleJS.createElement('h1', {}, ['About'])); - Navigating:
Use the
Linkfunction to navigate programmatically:
This updates the URL usingSimpleJS.Link('/home');history.pushStateand triggers the router to render the corresponding component. - Router Initialization:
Call
SimpleJS.router()to start the router and render the component for the current URL.
Example with Routing
// In app/index.js
import { SimpleJS } from './simplejs.js';
SimpleJS.addRoute('/home', () => SimpleJS.createElement('h1', {}, ['Home']));
SimpleJS.addRoute('/about', () => SimpleJS.createElement('h1', {}, ['About']));
const app = () => SimpleJS.createElement('div', {}, [
SimpleJS.createElement('button', { onClick: () => SimpleJS.Link('/home') }, ['Go to Home']),
SimpleJS.createElement('button', { onClick: () => SimpleJS.Link('/about') }, ['Go to About']),
SimpleJS.router()
]);How It Works
DOM Abstraction
- Virtual DOM: UI is represented as a tree of JavaScript objects (e.g.,
{ tag: 'div', attrs: {}, children: [] }). - Rendering:
SimpleJS.renderconverts virtual DOM nodes to real DOM elements initially. - Diffing:
updateElementcompares old and new virtual DOMs, updating the real DOM efficiently.
Event Handling
- Custom System: Events like
onClickare specified in theattrsobject. - Listener Tracking: Each real DOM element has an
_listenersobject to store event handlers, ensuring they can be removed or updated during diffing. - Why It Works: Prevents duplicate listeners and ensures the real DOM matches the virtual DOM’s event intent.
State Management
- Global State: Stored in
SimpleJS.state, updated viasetState. - Reactivity: State changes trigger a new virtual DOM, which is diffed against the old one to update the UI.
Routing
- Path-Based: Uses
window.location.pathnameto manage app state. - Navigation: The
Linkfunction updates the URL withhistory.pushStateand triggersrouter()to render the matching component. - Sync: URL changes trigger re-renders with diffing applied.
Diffing Algorithm
- Purpose: Reduces DOM manipulations by updating only changed parts.
- Process:
- Tag Check: If tags differ, replace the entire element.
- Attributes: Update or remove attributes/event listeners as needed, using
element._listenersfor event management. - Keys for Lists: Add a
keyattribute to virtual DOM nodes for better list diffing (use unique IDs, not indexes). - Children: Recursively update, replace, add, or remove child nodes.
- Why It Works: By comparing old and new virtual DOMs, only necessary changes are applied, improving performance over full re-renders.
