Package Exports
- webjsx
- webjsx/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (webjsx) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
webjsx
webjsx is a lightweight virtual DOM library for building web applications with JSX and Web Components. It offers a minimal approach to creating, diffing, and rendering virtual nodes for efficient DOM updates. webjsx is NOT a framework - it's a library.
Installation
Install webjsx via npm:
npm install webjsxGetting Started
The easiest way to get started with webjsx is by setting up a project using your preferred build tools. Below is a basic example of how to create and render elements using webjsx with a focus on JSX and Web Components.
Creating Elements with JSX
webjsx fully supports JSX syntax, enabling you to write more readable and maintainable code. Use the createElement function to create virtual DOM elements and the applyDiff function to render them to the real DOM.
/** @jsx webjsx.createElement */
import * as webjsx from "webjsx";
// Define a simple virtual DOM element using JSX
const vdom = (
<div id="container">
<h1>Welcome to webjsx</h1>
<p>This is a simple example.</p>
</div>
);
// Select the container in the real DOM
const container = document.getElementById("app");
// Apply the virtual DOM diff to update the real DOM
applyDiff(container, vdom);Defining and Using Web Components with JSX
webjsx excels at integrating JSX with Web Components, allowing you to define custom elements and render them using JSX syntax.
/** @jsx webjsx.createElement */
import * as webjsx from "webjsx";
// Define a custom Web Component
class MyElement extends HTMLElement {
static get observedAttributes() {
return ["title", "count"];
}
constructor() {
super();
this._count = 0;
}
connectedCallback() {
this.render();
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "title" || name === "count") {
this.render();
}
}
set count(val) {
this._count = val;
this.render();
}
get count() {
return this._count;
}
render() {
// Use webjsx's applyDiff to render JSX inside the Web Component
const vdom = (
<div>
<h2>{this.getAttribute("title")}</h2>
<p>Count: {this.count}</p>
</div>
);
applyDiff(this, vdom);
}
}
// Register the custom element
if (!customElements.get("my-element")) {
customElements.define("my-element", MyElement);
}
// Create a virtual DOM with the custom Web Component
const vdom = <my-element title="Initial Title" count={10}></my-element>;
// Render the custom Web Component
const container = document.getElementById("app");
applyDiff(container, vdom);Handling Events in JSX
Attach event listeners directly within your JSX using standard HTML event attributes.
/** @jsx webjsx.createElement */
import { createElement, applyDiff } from "webjsx";
// Define an event handler
const handleClick = () => {
alert("Button clicked!");
};
// Create a button with an onclick event
const Button = () => {
return <button onclick={handleClick}>Click Me</button>;
};
// Render the Button component
const container = document.getElementById("app");
applyDiff(container, <Button />);Using Fragments
Group multiple elements without introducing additional nodes to the DOM using Fragment.
/** @jsx webjsx.createElement */
import * as webjsx from "webjsx";
const List = () => {
return (
<Fragment>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</Fragment>
);
};
const container = document.getElementById("app");
applyDiff(
container,
<ul>
<List />
</ul>
);API Reference
createElement
Creates a virtual DOM element.
Usage:
createElement(type, props, ...children);type:string|typeof Fragment
The type of the element, e.g.,'div','span', orFragmentfor grouping.props:object | null
An object containing attributes and properties for the element.children:VNode | VNode[]
The child elements or text content.
Example:
createElement("div", { id: "main" }, "Hello, World!");applyDiff
Applies the differences between the new virtual node(s) and the existing DOM.
Usage:
applyDiff(parent, newVirtualNode);parent:Node
The parent DOM node where the virtual nodes will be applied.newVirtualNode:VNode | VNode[]
A single virtual node or an array of virtual nodes.
Example:
const vdom = createElement("p", { class: "text" }, "Updated Text");
applyDiff(container, vdom);Fragment
A special type used to group multiple elements without adding extra nodes to the DOM.
Usage:
<Fragment>
<Element1 />
<Element2 />
</Fragment>Example:
<Fragment>
<span>First</span>
<span>Second</span>
</Fragment>Creating Web Components with JSX
webjsx simplifies the creation and rendering of Web Components using JSX. By leveraging the power of JSX, you can define complex custom elements with ease.
Example: Creating a Counter Web Component
/** @jsx webjsx.createElement */
import { createElement, applyDiff } from "webjsx";
// Define the custom Web Component
class CounterElement extends HTMLElement {
static get observedAttributes() {
return ["title", "count"];
}
constructor() {
super();
this._count = 0;
}
connectedCallback() {
this.render();
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "title" || name === "count") {
this.render();
}
}
set count(val) {
this._count = val;
this.render();
}
get count() {
return this._count;
}
render() {
// Render JSX inside the Web Component
const vdom = (
<div>
<h2>{this.getAttribute("title")}</h2>
<p>Count: {this.count}</p>
<button onclick={this.increment.bind(this)}>Increment</button>
</div>
);
applyDiff(this, vdom);
}
increment() {
this.count += 1;
}
}
// Register the custom element
if (!customElements.get("counter-element")) {
customElements.define("counter-element", CounterElement);
}
// Create and render the CounterElement
const vdom = <counter-element title="My Counter" count={0}></counter-element>;
const container = document.getElementById("app");
applyDiff(container, vdom);Testing
webjsx comes with a comprehensive test suite to ensure reliability and correctness. The tests cover various aspects, including basic rendering, element management, event handling, fragments, keys handling, multiple updates, props handling, and integration with custom Web Components.
To run the tests:
npm testEnsure that all tests pass before deploying your application.
Building
webjsx is written in TypeScript and can be built using standard TypeScript and bundling tools.
TypeScript Configuration
Ensure your tsconfig.json is set up to handle JSX and module resolution correctly.
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "webjsx.createElement",
"jsxFragmentFactory": "webjsx.Fragment",
"target": "es6",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true
}
}Running the Build
npm run buildEnsure that your build scripts are correctly defined in package.json.
Example Projects
Explore these example projects to see webjsx in action:
- Basic Rendering: Demonstrates simple element creation and rendering.
- Event Handling: Shows how to attach and manage event listeners.
- Fragments and Keys: Illustrates grouping elements and optimizing list rendering.
- Custom Web Components: Integrates custom elements with webjsx.
- JSX Syntax with Web Components: Focuses on rendering Web Components using JSX.
Contributing
Contributions are welcome! Whether it's reporting bugs, suggesting features, or submitting pull requests, your help is appreciated.
- Fork the repository.
- Create a new branch:
git checkout -b feature-name. - Commit your changes:
git commit -m 'Add new feature'. - Push to the branch:
git push origin feature-name. - Open a pull request.
Please ensure that your contributions adhere to the project's coding standards and include appropriate tests.
License
webjsx is open-source software licensed as MIT.
Support
If you encounter any issues or have questions, feel free to open an issue on GitHub or reach out via Twitter @jeswin.