Understanding Metric vs Imperial Systems
The metric system, officially known as the International System of Units (SI), is used by the vast majority of countries worldwide. Meanwhile, the United States, Liberia, and Myanmar continue to use the imperial system for everyday measurements.
Volume: Gallons and Liters
One of the most common conversions travelers and international traders deal with is between gallons and liters. A US gallon equals approximately 3.785 liters. Try the converter below to see how these units relate:
Interactive Component: Unit Converter
This difference can be particularly significant when comparing fuel efficiency. European cars advertise consumption in liters per 100 kilometers, while American vehicles use miles per gallon.
Temperature: Fahrenheit and Celsius
Temperature conversion is another common need. The formula is:
C = (F - 32) x 5/9. Water freezes at 32°F (0°C) and boils at
212°F (100°C).
Interactive Component: Temperature Converter
"The metric system is the tool of the devil! My car gets 40 rods to the hogshead and that's the way I likes it!" — Grandpa Simpson
Dynamic Integration with External JavaScript
One of the unique features of this framework is how seamlessly components integrate with existing JavaScript code. You can manipulate component attributes using standard DOM APIs, attach vanilla event listeners, and pass complex data structures.
1. DOM Attribute Manipulation
When you update a component's attributes using setAttribute(),
the changes automatically propagate into the component and trigger re-renders:
Attribute-Reactive Component
External Controls (Vanilla JS)
2. Vanilla JS Event Handlers
Components emit standard DOM events that you can listen to with
addEventListener(). This allows components to communicate
with legacy code or other frameworks:
Event-Emitting Counter
External Event Listeners
3. Setting Props Directly (Rich Data)
VDX components expose their props as properties on the DOM element. You can set any prop directly - including arrays, objects, and functions - without needing custom setter methods:
Data-Driven Component
Inject Data via JavaScript
4. JSON Hydration for Static Site Generation
For static site generators (Hugo, Jekyll, Eleventy, etc.), you can pass complex data
to components using json-* attributes that either contain JSON or reference
<script type="application/json"> elements.
The latter avoids HTML escaping issues and keeps data readable:
SSG-Friendly Data Hydration
How it works:
<!-- Component with json-* attribute -->
<country-list json-countries="ssg-countries-data" title="..."></country-list>
<!-- JSON data in a script tag (easy for SSG templates to generate) -->
<script type="application/json" id="ssg-countries-data">
[
{"flag": "🇯🇵", "name": "Japan", "capital": "Tokyo"},
{"flag": "🇦🇺", "name": "Australia", "capital": "Canberra"}
]
</script>
Benefits: No HTML escaping needed for quotes or special characters.
The JSON stays formatted and readable. Multiple components can share the same data source.
The json-* attribute is removed after hydration.
5. Two-Way External Binding
You can also read component state and react to changes. This shopping cart demonstrates bidirectional communication between the component and external code:
Shopping Cart with External Sync
External Cart Manipulation
6. Children Props (React-style Composition)
Components can accept child elements just like React. This enables powerful composition patterns where you wrap static content with reactive behavior:
Collapsible Section with Static Children
This paragraph is static HTML written directly in the page.
The collapsible-section component wraps it and adds interactive expand/collapse
behavior. The children are passed via this.props.children.
- List items work too
- Any HTML can be a child
- Including other components!
This section starts expanded because we set expanded="true".
Each component instance maintains its own state independently.
7. Nested Component Hydration
The most powerful feature: you can nest VDX components inside other components in your static HTML, and they all hydrate properly. This enables static site generators to render component trees that come alive in the browser:
Component Tree from Static HTML
These converters below are fully functional VDX components nested inside another VDX component, all defined in static HTML:
This pattern is perfect for static site generators (Hugo, Jekyll, 11ty) - render component markup server-side, and VDX hydrates them client-side.
Summary
These examples demonstrate how VDX components behave like native HTML elements while providing React-like reactivity. Key integration points:
| Feature | How to Use |
|---|---|
| Set props directly | element.propName = value (works with arrays, objects, functions) |
| Update string attributes | element.setAttribute('name', 'value') |
| Listen to events | element.addEventListener('custom-event', handler) |
| Read component state | element.getState() or element.state |
| Pass children | Place HTML inside component tags, access via this.props.children |
| Nested components | VDX components in static HTML children hydrate automatically |
| JSON hydration (SSG) | json-propName="script-id" + <script type="application/json" id="script-id"> |
Important: Component Boundaries
Warning: Components are a boundary between vanilla JS and VDX. The framework manages everything inside a component's template. Do not use DOM manipulation (likeappendChild,innerHTML, orremoveChild) on elements inside a component - the virtual DOM will overwrite your changes on the next render.
Safe pattern: Components as islands in a static page. Your vanilla JS page contains VDX components, but doesn't reach inside them.
<!-- GOOD: Static page with component islands -->
<header>Static header</header>
<main>
<p>Static content...</p>
<unit-converter></unit-converter> <!-- Component island -->
<p>More static content...</p>
</main>
<footer>Static footer</footer>
Avoid: Wrapping your entire static page in a VDX component, as the framework will expect to manage all DOM inside it.
<!-- BAD: Don't wrap static content in a component -->
<site-wrapper>
<header>...</header>
<main>...your entire site...</main>
<footer>...</footer>
</site-wrapper>