> **>>> TL;DR:** This provides a minimal vanilla JS base class that aims to reduce the complexity of creating reactive custom elements. See the [Quick Start Example](#quick-start-example) Web Component Base --- [![Package information: NPM version](https://img.shields.io/npm/v/web-component-base)](https://www.npmjs.com/package/web-component-base) [![Package information: NPM license](https://img.shields.io/npm/l/web-component-base)](https://www.npmjs.com/package/web-component-base) [![Package information: NPM downloads](https://img.shields.io/npm/dt/web-component-base)](https://www.npmjs.com/package/web-component-base) When you extend the `WebComponent` class for your component, you only have to define the `template` and `properties`. Any change in any property value will automatically cause just the component UI to render. The result is a reactive UI on property changes. ## Table of Contents 1. [Import via unpkg](#import-via-unpkg) 1. [Installation via npm](#installation-via-npm) 1. [Usage](#usage) 1. [`template` vs `render()`](#template-vs-render) 1. [Quick Start Example](#quick-start-example) 1. [Life-Cycle Hooks](#life-cycle-hooks) 1. [`onInit`](#oninit) - the component is connected to the DOM, before view is initialized 1. [`afterViewInit`](#afterviewinit) - after the view is first initialized 1. [`onDestroy`](#ondestroy) - the component is disconnected from the DOM 1. [`onChanges`](#onchanges) - every time an attribute value changes ## Import via unpkg Import using [unpkg](https://unpkg.com/web-component-base) in your vanilla JS component. We will use this in the rest of our [usage examples](#usage). ```js import WebComponent from "https://unpkg.com/web-component-base/index.js"; ``` ## Installation via npm Usable for projects using typescript, or with bundlers, or using import maps. ```bash npm i web-component-base ``` ## Usage In your component class: ```js // HelloWorld.mjs import WebComponent from "https://unpkg.com/web-component-base/index.js"; class HelloWorld extends WebComponent { name = "World"; emotion = "excited"; static properties = ["name", "emotion"]; get template() { return `

Hello ${this.name}${this.emotion === "sad" ? ". 😭" : "! 🙌"}

`; } } customElements.define('hello-world', HelloWorld); ``` In your HTML page: ```html ``` The result is a reactive UI that updates on attribute changes: UI showing feeling toward Web Components changing from SAD to EXCITED ## `template` vs `render()` This mental model attempts to reduce the cognitive complexity of authoring components: 1. The `template` is a read-only property (initialized with a `get` keyword) that represents *how* the component view is rendered. 1. There is a `render()` method that triggers a view render. 1. This `render()` method is *automatically* called under the hood every time an attribute value changed. 1. You can *optionally* call this `render()` method at any point to trigger a render if you need. ## Quick Start Example Here is an example of using a custom element in a single .html file: ```html WC Base Test ``` ## Life-Cycle Hooks Define behavior when certain events in the component's life cycle is triggered by providing hook methods ### onInit() - Triggered when the component is connected to the DOM - Best for setting up the component ```js import WebComponent from "https://unpkg.com/web-component-base/index.js"; class ClickableText extends WebComponent { // gets called when the component is used in an HTML document onInit() { this.onclick = () => console.log(">>> click!"); } get template() { return `Click me!`; } } ``` ### afterViewInit() - Triggered after the view is first initialized ```js class ClickableText extends WebComponent { // gets called when the component's innerHTML is first filled afterViewInit() { const footer = this.querySelector('footer'); // do stuff to footer after view is initialized } get template() { return ``; } } ``` ### onDestroy() - Triggered when the component is disconnected from the DOM - best for undoing any setup done in `onInit()` ```js import WebComponent from "https://unpkg.com/web-component-base/index.js"; class ClickableText extends WebComponent { clickCallback() { console.log(">>> click!"); } onInit() { this.onclick = this.clickCallback; } onDestroy() { console.log(">>> removing event listener"); this.removeEventListener("click", this.clickCallback); } get template() { return `Click me!`; } } ``` ### onChanges() - Triggered when an attribute value changed ```js import WebComponent from "https://unpkg.com/web-component-base/index.js"; class ClickableText extends WebComponent { // gets called when an attribute value changes onChanges(changes) { const {property, previousValue, currentValue} = changes; console.log('>>> ', {property, previousValue, currentValue}) } get template() { return `Click me!`; } } ```