Understanding Metric vs Imperial Systems

Published December 2024 | Educational Content

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

[Ready] Listening for events...

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

External Total Display: $0.00

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:

Temperature:
Volume:

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 (like appendChild, innerHTML, or removeChild) 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>