DEV Community

loading...

Let's Make Components with HTML!

tamb profile image Tamb Updated on ・2 min read

Sometimes you work on front-end teams that use bleeding edge tech... Sometimes you inline all your CSS...
Most of the time, you're somewhere in between. And that's a reasonable place to be.

A lot of people are using Virtual DOM implementation for everything. And I've been seeing fewer people using Bootstrap or native DOM Manipulation. In fact, there are articles out there thate say to NEVER manipulate the DOM directly. That really doesn't make sense. The DOM exposes an API and APIs are meant to be used.

So the question is, how the H do you create standards for making Component-driven (ie: reusable) Markup without a thick abstraction layer?

I've been working in teams that use template engines like JSP, Thymeleaf, Pug, for years now. At first, the Revealing Module pattern was a life saver. This was how I wrote all my features (it also used to include jQuery). All of my DOM queries were based on HTML classes like class="js-button" or class="js-counter". And if I had nested classes I had to start getting more and more specific with my names.

So a counter might look like this:

<div class="counter">
  <p class="js-count">
   12
  </p>
  <button class="js-minus">
   -
  </button>
  <button class="js-plus">
   +
  </button>
</div>

I then had to use addEventListener and cache DOM in variables and throw it all inside a module.

This did NOT scale well. Not only did my js-dependent classes get mixed up with my styling classes, but I had to read through my entire component javascript just to see what HTML was necessary. It became a nightmare when it started growing.

So I started messing around and chatting with other devs, and I began compiling a bunch of standards. I packaged these all into a very small < 2kb framework for creating vanilla components with declarative HTML.

It's called Domponent

And it made my guesswork above into something declarative and lightweight"


<div data-component="Counter">
  <p data-bind="state:Counter.count">0</p>
  <button data-action="click->Counter.decrement">
    -1
  </button>
  <button data-action="click->Counter.increment">
    +1
  </button>
</div>

And when using it you don't need to add additional eventListeners or cache DOM nodes, you can declare it all in your HTML and the framework will wire things up for you. So all the JS you need to write is this:

import { Component } from "domponent";

export default class Counter extends Component {
  constructor(el) {
    super(el);
  }

  increment() {
    this.setState({ count: this.state.count + 1 });
  }

  decrement() {
    this.setState({ count: this.state.count - 1 });
  }
}

Looks kinda like a React component, feels kinda like regular ol DOM. It's Domponent.

Check it out. See if the extra 2kb might make your next project easier to reason about. Even if you don't use it, check out the data-api for a good idea of some standards that may make your life a boat load simpler!

Peace and Love,

Tamb

Discussion (0)

pic
Editor guide