Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/nathanjhood/web-components
How to OOP in the browser.
https://github.com/nathanjhood/web-components
browser javascript no-config oop web-component web-components webcomponent webcomponents
Last synced: 28 days ago
JSON representation
How to OOP in the browser.
- Host: GitHub
- URL: https://github.com/nathanjhood/web-components
- Owner: nathanjhood
- Created: 2024-10-12T17:00:08.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2024-10-18T00:38:29.000Z (29 days ago)
- Last Synced: 2024-10-18T18:33:36.318Z (28 days ago)
- Topics: browser, javascript, no-config, oop, web-component, web-components, webcomponent, webcomponents
- Language: TypeScript
- Homepage: https://nathanjhood.github.io/web-components/
- Size: 246 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Web Components
OOP in the browser!
```html
(...)
"Your App Goes Here!"
```
- No config
- No framework
- No abstractionsJust raw [Web API](https://developer.mozilla.org/en-US/docs/Web/API).
Powered by TailwindCSS, ESBuild, and fast-refreshing development server!
## How to...
Step by step!
- [`start`](#start)
- [`class AppComponent {}`](#class-appcomponent-)
- [`AppComponent.constructor()`](#appcomponentconstructor)
- [`AppComponent extends HTMLElement`](#appcomponent-extends-htmlelement)
- [`HTMLElement.super()`](#htmlelementsuper)
- [`this`](#this)
- [`AppComponent.innerHtml`](#appcomponentinnerhtml)
- [`CustomElementRegistry`](#customelementregistry)
- [`'app-component': AppComponent`](#app-component-appcomponent)
- [`AppComponent.render()`](#appcomponentrender)
- [`AppComponent.render(innerHTML)`](#appcomponentrenderinnerhtml)
- [`AppComponent.setup()`](#appcomponentsetup)
- [`createElement('app-component')`](#createelementapp-component)
- [`App()`](#app)
- [`render(App)`](#renderapp)
- [``](#app-component)
- [Tips](#tips)
- [Further Reading](#further-reading)### `start`
```sh
$ git clone [email protected]:nathanjhood/web-components.git
``````sh
$ cd web-components
``````sh
$ npm install
``````sh
# For Windows...
$env:NODE_ENV="development"# For Linux/Mac...
export NODE_ENV="development"
``````sh
$ npm run start
``````ts
# ...Rebuilding...
Done in 1623ms.
Server running at http://127.0.0.1:3000/
To exit: Ctrl + c```
[Open in your browser](http://localhost:3000) and edit `src/App.js` - the page will automatically refresh itself after every save.
---
### `class AppComponent {}`
```js
// src/App.jsclass AppComponent {}
```---
### `AppComponent.constructor()`
```js
class AppComponent {
constructor() {/** setup goes here... */}
}
```---
### `AppComponent extends HTMLElement`
```js
// "I am a HTMLElement"class AppComponent extends HTMLElement {
constructor() {}
}// "...plus more ;) "
```---
### `HTMLElement.super()`
```js
class AppComponent extends HTMLElement {
constructor() {
super(); // MUST do this first...
}
}
```---
### `this`
```js
class AppComponent extends HTMLElement {
constructor() {
// inside here, "this" means "this 'AppComponent'"...super();
this. // <-- '.' should produce a long list of props and methods...
}
}
```---
### `AppComponent.innerHtml`
```js
// 'innerHTML' === innerHTMLclass AppComponent extends HTMLElement {
constructor() {
super();
this.innerHTML = `Your app goes here`;
}
}
```### `CustomElementRegistry`
```js
// IMPORTANT
window.customElements.define('app-component', AppComponent);
```---
### `'app-component': AppComponent`
```js
window.customElements.define('app-component', // <-- wrap the class!
class AppComponent extends HTMLElement {
constructor() {
super();
this.innerHTML = `Your app goes here`;
}
}
); // <-- '.define()' ends here!
```---
### `AppComponent.render()`
```js
window.customElements.define('app-component',
class AppComponent extends HTMLElement {
constructor() {
super();
this.innerHTML = this.render();
}
render() {
return `Your app goes here`;
}
}
);
```---
### `AppComponent.render(innerHTML)`
```js
window.customElements.define('app-component',
class AppComponent extends HTMLElement {
constructor() {
super();
this.innerHTML = this.render('Your app goes here');
}
render(innerHTML) {
return `${innerHTML}`;
}
}
);
```---
### `AppComponent.setup()`
```js
window.customElements.define('app-component',
class AppComponent extends HTMLElement {
constructor() {
super();
this.setup();
}
setup() {
this.innerHTML = this.render('Your app goes here');
}
render(innerHTML) {
return `${innerHTML}`;
}
}
);
```---
### `createElement('app-component')`
```js
window.customElements.define('app-component',
class AppComponent extends HTMLElement {
constructor() {
super();
this.setup();
}
setup() {
this.innerHTML = this.render('Your app goes here');
}
render(innerHTML) {
return `${innerHTML}`;
}
}
);const app = document.createElement('app-component');
```---
### `App()`
```js
const App = () => {
// define the component
window.customElements.define('app-component',
class AppComponent extends HTMLElement {
constructor() {
super();
this.setup();
}
setup(): void {
this.innerHTML = this.render('Your app goes here');
}
render(innerHTML) {
return `${innerHTML}`;
}
}
);
// then return it
return document.createElement('app-component');
}// Now we can assign it :)
const app = App();
```---
### `render(App)`
```js
// src/index.jsimport App = require('./App');
const render = (element) = {
// ...attaches passed-in element to document
}// so, pass it our App :)
render(App)```
---
### ``
```html
```
```html
#shadowRoot (open)
"Your App Goes Here!"
```
---
## Tips
---
### functional approach
```js
// example:const Button = () => {
return document.createElement('button')
}// HTMLButtonElement
const button = Button();```
---
### factory method
```js
// exampleconst CustomButton = () => {
class CustomButtonElement extends HTMLButtonElement {
constructor() {
super();
}
}
customElements.define('custom-button', CustomButtonElement)
return document.createElement('custom-button');
};// CustomButtom
const customButton = CustomButton();
```---
### passing props
```js
/**
* @typedef CustomButtonProps
* @property {'submit' | 'reset' | 'button'} type
*//**
* @param {CustomButtonProps} props
* @returns {HTMLButtonElement}
*/
const CustomButton = (props) => {
class CustomButtonElement extends HTMLButtonElement {
constructor() {
super();
this.type = props.type;
}
}
customElements.define('custom-button', CustomButtonElement);
return document.createElement('custom-button');
};const customButton = CustomButton({ type: 'submit' });
```
---
### adding children
```js
/**
* @typedef CustomButtonProps
* @property {'submit' | 'reset' | 'button'} type
* @property {Node | undefined} children
*//**
* @param {CustomButtonProps} props
* @returns {HTMLButtonElement}
*/
const CustomButton = (props) => {
class CustomButtonElement extends HTMLButtonElement {
constructor() {
super();
this.type = props.type;
if (props.children) this.appendChild(props.children);
}
}
customElements.define('custom-button', CustomButtonElement);
return document.createElement('custom-button');
};const customButtonA = CustomButton({ type: 'submit' });
const customButtonB = CustomButton({ type: 'submit', children: customButtonA });```
---
### adding styles
```js
/**
* @typedef CustomButtonProps
* @property {'submit' | 'reset' | 'button'} type
* @property {Node | undefined} children
* @property {string | undefined} className
*//**
* @param {CustomButtonProps} props
* @returns {HTMLButtonElement}
*/
const CustomButton = (props) => {
class CustomButtonElement extends HTMLButtonElement {
constructor() {
super();
this.type = props.type;
if (props.children) this.appendChild(props.children);
if (props.className) this.className = props.className;
}
}
customElements.define('custom-button', CustomButtonElement);
return document.createElement('custom-button');
};const tailwindButton = CustomButton({
type: 'submit',
className: 'flex align-left text-white bg-red-500',
});```
---
## Further Reading
- [webcomponents.org](https://www.webcomponents.org/)
- [eisenebergeffect @ Medium: Hello Web Components](https://eisenbergeffect.medium.com/hello-web-components-795ed1bd108e)
- [MDN's Web Component examples](https://github.com/mdn/web-components-examples)
- [MDN's Web API glossary](https://developer.mozilla.org/en-US/docs/Web/API)
- [MDN's Web API - HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement)
- [Building Interoperable Web Components (including React)](https://css-tricks.com/building-interoperable-web-components-react/)[Read me on github.com](https://github.com/nathanjhood/web-components)
[Read me on nathanjhood.github.io](https://nathanjhood.github.io/web-components)