🕸️

Web Component

Tags
web
Component
Date
2021/10/06
속성

개요

일반적으로 가능한 코드를 재사용하는 것이 좋다는 것을 알고있다. 그러나 전통적으로 마크업 구조에서는 이것이 쉽지 않았다. 때문에 현대 웹 개발을 할 때 React, Vue 와 같은 front library 를 사용해서 component based develop 을 하고있다. 그러나 React 를 사용하지 않고 순수 javascript 로도 component based develop 이 가능하다. 그것을 가능하게하는 요소들에 대해서 한 번 알아보자

Custom Element

web developer 들은 기존의 HTML tag 의 기능들을 강화하거나 확장해서 사용할 수 있다!
HTML 은 충분히 훌륭하지만 어휘 및 확장성에 제한이 있었다.
customElements 라는 명령어를 사용해 custom html 을 정의한다.
class AppDrawer extends HTMLElement { // A getter/setter for an open property. get open() { return this.hasAttribute('open'); } set open(val) { // Reflect the value of the open property as an HTML attribute. if (val) { this.setAttribute('open', ''); } else { this.removeAttribute('open'); } this.toggleDrawer(); } // A getter/setter for a disabled property. get disabled() { return this.hasAttribute('disabled'); } set disabled(val) { // Reflect the value of the disabled property as an HTML attribute. if (val) { this.setAttribute('disabled', ''); } else { this.removeAttribute('disabled'); } } // Can define constructor arguments if you wish. constructor() { // If you define a constructor, always call super() first! // This is specific to CE and required by the spec. super(); // Setup a click listener on <app-drawer> itself. this.addEventListener('click', e => { // Don't toggle the drawer if it's disabled. if (this.disabled) { return; } this.toggleDrawer(); this.innerHTML = '<div>wow</div>' }); } toggleDrawer() { ... } } window.customElements.define('app-drawer', AppDrawer);
JavaScript
복사
/* usage */ <app-drawer> ... </app-drawer>
HTML
복사
class FancyButton extends HTMLButtonElement { ... }
JavaScript
복사
기존의 HTML 을 상속받는다 ⇒ 기존 HTMLElement 의 기능을 가지고 있음. 위에서 보듯 this 를 통해서 element 에 접근이 가능하기 때문에 event 를 붙이는 등 customizing 이 가능함.
그리고 위와 같이 만들어진 custom element 또한 확장(extends)해서 새로운 custom element 를 생성 가능하다.
Search
Lifecycle hooks
Name
description
element 가 DOM 에 추가될 때마다 호출됨. resources fetching, rendering 할 때 유용함.
element 가 DOM 에서 제거될 때마다 호출됨. 이벤트 등 code clean 할 때 유용함. (그러나 tab 을 닫는다거나 등의 액션에는 반응하지 않음)
observed 된 attribute 들이 추가, 삭제, 수정 될 때마다 호출됨. (참고)
새로운 document 로 custom element 가 이동할 때 호출됨.

Rules

custom element 의 이름은 dash 가 붙어야함.(<x-tags>, <my-element>) . html parser 가 기존 html 과 custom elements 를 구분하기 위해서임.
동일한 태그에 대해서는 한 번만 등록이 가능. 중복 등록 시 DOMException 발생
custom element 는 self closing 이 불가능함. 오직 허락된 몇 개의 tag 들만 self closing 이 가능하기 때문

Browser Support

장점

모듈식 코드
less code
재사용성 강화

Shadow DOM

what is shadow dom

캡슐화된 "그림자" DOM 트리를 엘리먼트 — 메인 다큐먼트 DOM 으로부터 독립적으로 렌더링 되는 — 를 추가하고 연관된 기능을 제어하기 위한 JavaScript API 의 집합. 이 방법으로 엘리먼트의 기능을 프라이빗하게 유지할 수 있어, 다큐먼트의 다른 부분과의 충돌에 대한 걱정 없이 스크립트와 스타일을 작성할 수 있음
shadow host - shadow dom 이 붙을 일반적인 DOM
shadow tree - shadow dom 의 dom tree
shadow dom 내 style 및 동작은 shadow dom 안에서만 영향을 미침. 바깥에서는 어떤 영향도 미치지 않는다.
const elementRef = document.findByElementID('container'); let shadow = elementRef.attachShadow({mode: 'open'}); // javascript 를 통해서 접근 가능 let shadow = elementRef.attachShadow({mode: 'closed'}); // " 불가능 let myShadowDom = myCustomElem.shadowRoot; // if mode closed, it will return null myShadowDom.attachChild('<div>wow</div>');
JavaScript
복사
const header = document.createElement('header'); const shadowRoot = header.attachShadow({mode: 'open'}); shadowRoot.innerHTML = '<h1>Hello Shadow DOM</h1>'; // Could also use appendChild(). // header.shadowRoot === shadowRoot // shadowRoot.host === header
JavaScript
복사

장점

캡슐화
마크업 구조 및 스타일, javascript 를 페이지 내 다른 코드와 분리하고 서로 충돌하지 않으며 좋은 코드와 구조를 가지게 함.

creating shadow DOM for a custom element

customElements.define('fancy-tabs', class extends HTMLElement {   constructor() {     super(); // always call super() first in the constructor.     // Attach a shadow root to <fancy-tabs>.     const shadowRoot = this.attachShadow({mode: 'open'});     shadowRoot.innerHTML = `       <style>#tabs { ... }</style> <!-- styles are scoped to fancy-tabs! -->       <div id="tabs">...</div>       <div id="panels">...</div>     `;   }   ... });
Plain Text
복사

browser support

HTML Template

페이지에 순간 그려지지 않지만, javascript 를 통해서 instance 를 생성할 수 있는 HTML 코드를 담을 방법을 제공.
<table id="producttable"> <thead> <tr> <td>UPC_Code</td> <td>Product_Name</td> </tr> </thead> <tbody> <!-- 존재하는 데이터는 선택적으로 여기에 포함됩니다 --> </tbody> </table> <template id="productrow"> <tr> <td class="record"></td> <td></td> </tr> </template>
HTML
복사
// 템플릿 엘리먼트의 컨텐츠 존재 유무를 통해 // 브라우저가 HTML 템플릿 엘리먼트를 지원하는지 확인합니다 if ('content' in document.createElement('template')) { // 기존 HTML tbody 와 템플릿 열로 테이블을 인스턴스화합니다 var template = document.querySelector('#productrow'); // 새로운 열을 복제하고 테이블에 삽입합니다 var tb = document.querySelector("tbody"); var clone = document.importNode(template.content, true); td = clone.querySelectorAll("td"); td[0].textContent = "1235646565"; td[1].textContent = "Stuff"; tb.appendChild(clone); // 새로운 열을 복제하고 테이블에 삽입합니다 var clone2 = document.importNode(template.content, true); td = clone2.querySelectorAll("td"); td[0].textContent = "0384928528"; td[1].textContent = "Acme Kidney Beans 2"; tb.appendChild(clone2); } else { // HTML 템플릿 엘리먼트를 지원하지 않으므로 // 테이블에 열을 추가하는 다른 방법을 찾습니다. }
JavaScript
복사

browser support

use all

example

React vs Web Component

React와 웹 컴포넌트는 서로 다른 문제를 해결하기 위해 만들어졌습니다. 웹 컴포넌트는 재사용할 수 있는 컴포넌트에 강한 캡슐화를 제공하는 반면, React는 데이터와 DOM을 동기화하는 선언적 라이브러리를 제공합니다. from React official website
Search
Title
React
Web components
It is a JavaScript library for building UI interfaces for single-page applications.
It is a set of different technologies that allow us to create reusable and isolated elements.
Types of components include functional and class.
Types of components include custom elements, shadow DOM, and templates.
Component re-rendering based on state changes.
No state management.
Components are reusable in React only.
Interoperable.
No local styling. but js in style
CSS can be scoped using shadow DOMs.
React provides a unidirectional data flow pattern.
You have to implement data binding yourself.
Its ecosystem is incredibly vast and powerful. It has a large community and forever growing tools and libraries.
The ecosystem is not as vast as React’s ecosystem.
제일 큰 차이점은 아무래도 React 로 만든 컴포넌트는 React app 에서만 사용이 가능하다는 점이다. 반면 Web component 로 만들면 Angular 든 Vue 든 React 던 상관 없이 재사용 가능하다.

참고