2

On Using Web Component Libraries

 2 years ago
source link: https://dev.to/claviska/on-using-web-component-libraries-fmb
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

On Using Web Component Libraries

Sep 20

・3 min read

We tend to think of components as things that belong to a framework. After all, React has components, Vue has components, Angular has components…it's just how we've always used them.

Because of that, people tend to refer to Lit and FAST Element as frameworks, but they’re not. They’re libraries, and that’s an important distinction.

If you want a React component to work, you have to use it with React. If you want a Vue component to work, you have to use it with Vue. If you want an Angular component to work…well, you get the point.

With web components, the platform is the framework.

Naturally, a follow up question is "why do you need a library then?" The truth is that we don’t. We can create web components without a library. Here's a counter component written in pure JavaScript.

class MyCounter extends HTMLElement {
  static get observedAttributes() {
    return ['count'];
  }

  constructor() {
    super();
    this.state = {
      count: 0
    };
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <button type="button">
        Count:
        <span class="count">${this.state.count}</span>
      </button>
    `;
    this.handleClick = this.handleClick.bind(this);
  }

  connectedCallback() {
    this.shadowRoot.querySelector('button').addEventListener('click', this.handleClick);
  }

  disconnectedCallback() {
    this.shadowRoot.querySelector('button').removeEventListener('click', this.handleClick);
  }

  get count() {
    return this.state.count; 
  }

  set count(newCount) {
    this.state.count = newCount;
    this.update();
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'count') {
      this.state.count = Number(newValue);
      this.update();
    }
  }

  handleClick() {
    this.count = this.count + 1;
  }

  update() {
    this.shadowRoot.querySelector('.count').textContent = this.state.count;     
  }
}

customElements.define('my-counter', MyCounter);
Enter fullscreen modeExit fullscreen mode

We choose to use libraries to improve the the component authoring experience and abstract messy boilerplate into efficient, reusable modules. Here's a functionally equivalent counter built with Lit.

import { LitElement, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';

@customElement('my-counter')
class MyCounter extends LitElement {
  @property({ type: Number }) count = 0;

  handleClick() {
    this.count++;
  }

  render() {
    return html`
      <button type="button" @click=${this.handleClick}>
        Count: ${this.count}
      </button>
    `;
  }
}
Enter fullscreen modeExit fullscreen mode

Sure, we can bake features such as declarative rendering and reactivity into each and every component, but that’s not DRY. It would convolute the code and make our components larger and more difficult to maintain. That’s not what I want and it's probably not what my users want.

Alternatively, we could build those features ourselves and split them off into reusable modules — but that's just reinventing the wheel, isn't it?

When you think of it that way, using a library to build web components makes a lot of sense.


Aside: It’s been said that developer experience is the only benefit to using a library. While it’s true that benefits to the end user are marginalized with one-off components, it's worth noting that APIs such as those offered by Lit and FAST Element lead to less bugs due to reduced complexity and less code in the component itself. Consider the counter examples above. Which would you rather maintain?

This post originally appeared on the author's blog.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK