lit-html

지니씨·2023년 2월 26일
0

프론트엔드

목록 보기
58/87

https://lit.dev/

lit은 빠르고 가벼운 web components를 구축하기 위한 간단한 라이브러리
(lit 라이브러리 사용해서 web component 쉬운 문법으로 구현 (like 과거 polymer))
lit의 구성 요소는 표준 web component, 각 lit 컴포넌트는 UI의 독립형 단위
Lit 구성 요소는 HTML 요소이므로 모든 표준 요소 API를 가지고 있음

주요 기능

두가지 주요 API

  • The html template tag used to write templates.
  • The render() function used to render a template to a DOM container.

Lit으로 앱 구축 시 장점

  • vanilla 또는 다른 라이브러리를 사용한 웹 컴포넌트에 쉽게 적용 가능 (lit은 브라우저 기본 문법 사용)
  • 간단, 빠름, 가볍
// Import lit-html
import {html, render} from 'lit-html';

// Define a template
const myTemplate = (name) => html`<p>Hello ${name}</p>`;

// Render the template to the document
render(myTemplate('World'), document.body);

## Lit 문법 if, else 로 attribute 추가/삭제 https://stackoverflow.com/questions/61413842/litelement-dont-add-attribute-if-value-is-false

built-in directives

classMap
styleMap : 인라인스타일

when : 삼항식
choose : switch

map : repeat보다 작고 빠름
repeat : 키 함수를 사용하지 않는다면 map 과 유사하므로 map 사용 권장
join
range : index로 반복문 돌림
ifDefined : attribute 값이 undefined 나 null 이면 속성 자체를 제거


Lit 컴포넌트 컨셉

1. 구성요소 정의

decorator | customElements.define()
LitElement는 ReactiveElement, HTMLElement 를 상속함

2. 렌더링 (템플릿 정의)

https://lit.dev/docs/components/rendering
render() 메소드에 템플릿 작성
render 메소드에는 모든 JavaScript 포함 가능
렌더가능한 값

  • Primitive values like string, number, or boolean.
  • TemplateResult objects created by the html function.
    DOM Nodes.
  • The sentinel values nothing and noChange.
  • Arrays or iterables of any of the supported types.
  • This is almost identical to the set of values that can be rendered to a Lit child expression. The one difference is that a child expression can render an SVGTemplateResult, returned by the svg function. This kind of template result can only be rendered as the descendant of an element.

    render() 가이드
  • 구성 요소의 상태를 변경하지 마십시오.
  • 부작용이 발생하지 않도록 하십시오.
  • 구성 요소의 속성만 입력으로 사용하십시오.
  • 동일한 속성 값이 지정된 경우 동일한 결과를 반환합니다.
  • render() 밖에서 돔 업데이트 피하고 컴포넌트의 템플릿을 상태 함수로 표현하고 속성에 상태를 캡쳐하기
    (이벤트를 받아서 ui 업데이트를 하길 원한다면, 이벤트 리스너가 직접 돔을 조작하는 대신 render()에서 사용하는 반응 속성을 설정하도록)

https://lit.dev/docs/components/rendering/#composing-templates 진행중 ing

3. 반응형 속성 (컴포넌트의 주기 업데이트, 리렌더링 트리거)

https://lit.dev/docs/components/properties
Lit 구성 요소는 입력을 수신하고 상태를 JavaScript 클래스 필드 또는 속성으로 저장합니다.
반응형 속성은 변경 시 반응형 업데이트 주기를 트리거하고 구성 요소를 다시 렌더링하며 선택적으로 특성에 읽거나 쓸 수 있는 속성입니다.

  • reactive updates : Lit는 각 반응성 속성에 대해 게터/세터 쌍을 생성합니다. 비활성 속성이 변경되면 구성 요소가 업데이트를 예약
  • attribute handlling : attribute 변경 시 property 업데이트
  • superclass properties : 슈퍼 클래스에서 선언한 속성 옵션을 자동으로 적용합니다. 옵션을 변경하려는 경우가 아니면 속성을 다시 선언할 필요가 없습니다.
  • Element upgrade : 요소가 이미 DOM에 있는 후에 Lit 구성 요소가 정의된 경우, Lit는 업그레이드 로직을 처리하여 요소가 업그레이드될 때 요소에 설정된 모든 속성이 올바른 반응성 부작용을 트리거하도록 합니다.

public properties
: 컴포넌트의 public API
: 보통 public은 입력으로 처리
: 사용자 입력의 반응을 제외하고 컴포넌트의 public 속성을 바꾸면 안됨
(사용자 입력으로 public 속성 바뀔 시 속성 변경에 대한 이벤트를 내보내야(dispatch)함)

public reactive properties (public 프로퍼티?)

  • 선언 방법 (2가지)
    : decorators를 이용해 정의(js 사용 시 Babel이나 TypeScript 컴파일러와 같은 컴파일러를 사용해야 함) : class 필드의 static properties를 이용한 정의
  • JS에서 reactive properties를 정의할때 클래스 필드 사용 X 대신 요소 생성자에서 속성을 초기화해야 함
  • 클래스 필드에 reactive properties 선언시 주의
    : babel+js를 사용할때 babelrc에서 setPublicClassFields : true 로 설정
    : 구 버전 babel 사용 시 @babel/plugin-proposal-class-properties 플러그인 필요
  • property 옵션 https://lit.dev/docs/components/properties/#property-options
    attribute, converter, hasChanged, noAccessor, reflect, state, type,

internal reactive state (private 프로퍼티?)

  • 컴포넌트의 public API가 아닌 반응형 프로퍼티
  • 선언 방법 (2가지)
    : decorators를 이용해 정의 @state
    : 클래스 필드의 static properties를 이용한 정의
  • _속성명
  • internal reactive state를 업데이트하면 업데이트 주기가 트리거 됨
  • 유일한 옵션 : hasCanged

properties가 바뀌면 어떤일이 벌어지는가?

속성 변경으로 인해 구성 요소가 템플릿을 다시 렌더링하는 반응형 업데이트 주기가 트리거될 수 있습니다.
property가 변하면 아래 과정이 순차적으로 일어난다.
1. property의 setter 호출
2. setter는 컴포넌트의 requestUpdate 메소드 호출
3. property의 이전값과 새로운값이 비교됨

  • === 사용
  • property가 hasChanged 함수를 가지고있으면, it's called with the property's old and new values.
  1. 속성 변경이 감지되면 업데이트가 비동기식으로 예약됩니다. 업데이트가 이미 예약되어 있는 경우에는 단일 업데이트만 실행됩니다.
  2. 구성 요소의 업데이트 방법을 호출하여 변경된 속성을 특성에 반영하고 구성 요소의 템플릿을 다시 렌더링합니다.

개체 또는 어레이 속성이 변하는 경우
개체 또는 어레이 속성을 변환하는 경우 개체 자체가 변경되지 않았기 때문에 업데이트가 트리거되지 않습니다.

  • 불변 데이터 패턴
  • 업데이트를 수동으로 트리거

불변 객체와 함께 하향식 데이터 흐름이 가장 좋음
새 값을 렌더링해야 하는 모든 구성 요소가 변경되지 않은 데이터 트리의 일부는 해당 구성 요소에 의존하는 구성 요소를 업데이트하지 않으므로 가능한 한 효율적으로 수행됩니다.
데이터를 직접 변환하고 업데이트 요청을 호출하는 건 고급 사용 사례(변환된 데이터를 사용하는 모든 구성 요소 식별하고 각 구성 요소를 찾아 업데이트 요청해야함, 관리 어려움)

Attributes

https://lit.dev/docs/components/properties/#attributes 진행중 ing

Custom property accessros

Customizing change detection

4. 캡슐화된 스타일

컴포넌트의 shadow root 아래의 shadow dom 에만 스타일이 적용 됨

정적 스타일 클래스 필드

  • 거의 항상 구성요소에 스타일을 추가하는 가장 좋은 방법

CSS의 모든 표현식은 한 번 평가된 후 모든 인스턴스에 재사용됩니다.
super class의 스타일 상속 가능
지정된 스타일 내보내는 모듈 생성하여 스타일 공유 가능

쉐도우돔 스타일링

  • lit 템플릿은 기본적으로 shadow tree 안에 렌더링 됨
    도큐먼트 레벨의 스타일 <-> 쉐도우 트리 서로 영향 X
  • :host 셀렉터 : 쉐도우 트리를 소유하는 호스트 요소 (컴포넌트 가장 상위)
  • :host, :host()는 섀도 트리 외부의 스타일에도 영향을 받을 수 있으
    :host 및 :host() 규칙에서 설정한 스타일을 사용자가 재정의할 수 있는 기본 스타일로 고려
  • 자식요소를 렌더링하기 위해서 한개또는 더 많은 <slot> 요소를 포함해야 함
    shadyCSS 사용 시 제한 - ::sloted() 구문을 폴리필 친화적으로 사용하는 방법 ShadyCSS 제한 참조

스타일을 추가하는 다른 방법 (lit 템플릿에 스타일을 정의해야할 때) (2가지)
1. <style></style> 요소 추가

  • 인스턴스별로 스타일을 사용자 정의해야 할 때
  • ShadyCSS 폴리필을 사용하는 경우 인스턴스 단위 스타일은 지원되지 않습니다.
  • ShadyCSS 폴리필의 제한으로 인해 ShadyCSS에서
  1. 외부 스타일 시트 사용 (권장 X)
  • ShadyCSS 폴리필은 외부 스타일 시트를 지원하지 않습니다.
  • 외부 스타일은 로드하는 동안 FOUC(Flash-of-Styled Content)를 발생시킬 수 있습니다.
  • href 속성의 URL은 기본 문서에 상대적입니다. 앱을 빌드하는 중이고 자산 URL이 잘 알려진 경우에는 괜찮지만 재사용 가능한 요소를 빌드할 때는 외부 스타일시트를 사용하지 마십시오.

1,2 방법 모두 webcomponents/polyfills - shadyCSS 사용 시 제한되는 부분이 있음
https://github.com/webcomponents/polyfills/tree/master/packages/shadycss#limitations

동적으로 인스턴스에 클래스, 인라인 스타일 적용하기
classMap, styleMap (Built-in directives)
(https://lit.dev/docs/templates/directives/)

Theming
커스텀 웹 컴포넌트 위에 스타일 적용 (my-element 태그 CSS 선택자 사용)

lit-html에서 saas 사용하기?
https://stackoverflow.com/questions/61221405/lit-element-unable-to-load-scss-into-lit-element

5. 라이프사이클.

lit components 는 custom element 라이프사이클 메소드를 사용한다.
반응형 속성이 변경될 때 DOM에 변경사항을 렌더링하는 반응형 업데이트 주기를 도입한다.

custom element 라이프사이클 mdn
표준 사용자 지정 요소 수명 주기 메서드를 사용자 지정해야 하는 경우 표준 Lit 기능이 유지되도록 슈퍼 구현(예: super.connectedCallback())을 호출해야 합니다.

constructor()
element가 생성되거나 업그레이드(요소가 이미 DOM에 있는 이후에 사용자 지정 요소에 대한 정의가 로드되는 경우)될때 호출
requestUpdate() 메서드를 사용하여 비동기 업데이트를 요청하여 Lit 구성 요소가 업그레이드되면 즉시 업데이트를 수행합니다.

connectedCallback()
컴포넌트가 document에 붙었을때 호출(shadowRoot 생성 보장)
요소 외부의 노드에 이벤트 수신기를 추가
일반적으로 connectedCallback()에서 수행한 모든 작업은 요소의 연결이 끊겼을 때 취소되어야 합니다. (메모리 누수를 방지하기 위해 창에서 이벤트 리스너를 제거해야 함)

disconnctedCallback()
컴포넌트가 document에서 지워졌을 때 호출
반응형 업데이트 주기를 일시 중지합니다. 요소가 연결되면 다시 시작됩니다.
외부 이벤트 리스너 제거 (내부 이벤트 리스너는 제거할 필요 없음)

attributeCahngedCallback()
요소의 observedAttributes 중 하나가 변경될때 호출
lit은 이 콜백을 사용하여 속성의 변경사항을 반응형 속성에 동기화 (자동진행)
이 콜백을 구현할 필요가 거의 없습니다.

adoptedCallback()
component가 새 문서로 이동될 때 호출
lit은 이 콜백에 대한 동작이 없음
이 콜백은 문서를 변경할 때 요소 동작이 변경되어야 하는 고급 사용 사례에만 사용해야 합니다.

[reactive update cycle]
표준 사용자 지정 요소 수명 주기 외에도 Lit 구성 요소는 사후 업데이트 주기도 구현합니다.

반응형 업데이트 주기는 반응형 속성이 변경되거나 requestUpdate() 메서드가 명시적으로 호출될 때 트리거됩니다. Lit는 비동기식으로 업데이트를 수행하여 속성 변경사항이 일괄 처리되도록 합니다. 업데이트가 요청된 후 업데이트가 시작되기 전에 더 많은 속성이 변경되면 모든 변경사항이 동일한 업데이트에 캡처됩니다.

업데이트는 마이크로 태스크 타이밍에 발생합니다. 즉, 업데이트는 브라우저가 화면에 다음 프레임을 그리기 전에 발생합니다. 브라우저 타이밍에 대한 자세한 내용은 Jake Archibald의 마이크로 태스크 기사 참조(https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)
1. 하나 또는 그 이상의 프로퍼티가 변경되거나 requestUpdate()가 호출 될 때 업데이트가 예약됩니다.
2. 업데이트는 다음 프레임이 페인트 되기전에 수행됩니다.

  • 반영 속성이 설정됨
  • component의 render 함수가 호출되어 내부 dom업데이트
  1. 업데이트가 완료되고 updateComplete promise가 resolve 됨

https://lit.dev/docs/components/lifecycle/#changed-properties 진행중

Shadow DOM

lit components 는 shadow DOM을 사용하여 DOM을 캡슐화 함
분리되고 캡슐화된 별도의 DOM 트리를 요소에 추가

장점

  • dom scoping : document.querySelector 로 shadow DOM 요소 찾을 수 없으므로 글로벌 스크립트가 component 를 깰 수 없음
  • style scoping : shadow dom에 대해 캡슐화된 스타일 작성
  • composition : 내부 DOM을 포함하는 구성요소의 shadow root는 component의 자식과 별개, component의 내부 DOM에서 자식을 어떻게 렌더링할 지 선택 가능

레거시 브라우저 지원
lit의 polyfill-support 모듈 다운로드

Accessing nodes in the shadow DOM

Lit 은 기본적으로 shadow root 인 renderRoot에 component를 렌더링 한다.
내부 요소를 찾으려면 this.renderRoot.querySelector()같은 DOM 쿼리 API를 사용한다.
renderRoot는 항상 .querySelectorAll().children과 같은 API를 공유하는 shadow root 또는 요소여야 한다.
component 초기 렌더링 후에(ex. firstUpdated) 내부 DOM을 쿼리하거나 getter 패턴을 사용할 수 있다.
(@query, @queryAll, @queryAsync 데코레이터 사용도 가능)
@queryAsync
: updateComplete promise를 기다리는 대신 이것을 사용 가능
: @queryAsync에서 반환한 노드가 다른 속성 변경으로 인해 변경될 수 있는 경우에 유용

Rendering children with slots

하나 또는 그 이상의 요소를 포함해야함 자식 노드의 placeholder와 같은 역할

자식은 DOM tree 를 이동하지않고 의 자식처럼 렌더링 된다.

Accessing slotted children

slotchange이벤트와 함께 slot.assignedNodes, slot.assignedElements 메소드 사용 가능

Customizing the render root

Lit component는 렌더 루트(내부 DOM의 컨테이너 역할을 하는 DOM 노드) (기본 shadowRoot)가 있다.
Lit Element 에는 이 렌더 루트를 아래 두 방법으로 커스텀할 수 있다.

참고

Events

Lit 요소는 사용자 정의 이벤트를 디스패치할 수 있습니다. (ex. 메뉴 요소는 이벤트를 발송하여 선택한 항목이 변경되었음을 나타낼 수 있으며, 팝업 요소는 팝업을 열거나 닫을 때 이벤트를 발송할 수 있습니다.)

이벤트 수신

decorators를 사용하지 않는 경우 객체를 이벤트 리스너 식으로 전달하여 이벤트 리스너 옵션을 사용자 정의할 수 있습니다. 개체에는 handleEvent() 메서드가 있어야 하며 EventListener()를 추가하기 위한 options 인수에 일반적으로 나타나는 옵션을 포함할 수 있습니다.

Adding event listeners to the component or its shadow root
component constructor는 components에 이벤트리스너를 추가하기 좋은 곳임

구성 요소 자체에 이벤트 수신기를 추가하는 것은 이벤트 위임의 한 형태(코드를 줄이거나 성능을 향상시키기 위해 수행할 수 있음, 이벤트 처리를 중앙 집중화 하여 코드 줄일 수 있음, 버블이 발생하는 이벤트만 처리 가능)

그러나 component의 shadow dom에서 발생한 이벤트는 component의 이벤트 리스너가 이벤트를 수신할 때 대상이 다지 지정된다. 대상을 다시 지정하면 이벤트 위임이 방해될 수 있으며 이를 방지하기위해서 이벤트 수신기를 component의 shadow dom 자체에 추가할 수도 있습니다. constructor에서는 shadowRoot 에 접근할 수 없기에 createRenderRoot 메서드에 이벤트 수신기를 추가할 수 있다. createRenderRoot 에서 shodow root를 반환하는 것 이 중요하다.

다른 요소(window, document 등)에 이벤트 리스너 추가
구성 요소가 이벤트 리스너를 자신 또는 템플릿으로 지정된 DOM(ex. window, document 또는 기본 DOM의 일부 요소)을 제외한 다른 항목에 추가하는 경우, connectedCallback()에서 이벤트 리스너를 추가하고 disconnectedCallback() 에서 제거해야 함

이벤트 리스너에서의 this
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
인스턴스 or 컴포넌트

반복되는 항목의 이벤트를 들을 때 이벤트가 거품이 일 경우 이벤트 위임을 사용하는 것이 편리한 경우가 많습니다.

이벤트 디스패치

모든 DOM 노드는 dispatchEvent 메소드를 이용해 이벤트를 디스패치 할 수 있다.
event type, options을 지정해 event instance 생성 후 dispatchEvent에 전달한다.

bubble 옵션 : 이벤트가 DOM 트리에서 디스패치 요소의 상위로 이동할 수 있다. 이벤트가 이벤트 위임에 참여할 수 있도록 하려면 이 플래그를 설정하는게 중요 함
composed 옵션 : shadow dom tree 를 넘어서 이벤트를 디스패치 할 수 있도록 설정

https://lit.dev/docs/components/events/#when-to-dispatch-an-event 진행중 ing

shadow dom 안에서 이벤트 처리하기

표준 이벤트 시스템과 다른 몇가지를 이해하는 것이 중요
shadow dom은 'shadow'요소에 대한 세부 정보를 캡슐화 하는 dom의 범위 지정 메커니즘을 제공하기 위해 존재 한다.
shadow dom의 이벤트는 외부 dom 요소에서 특정 세부 정보를 캡슐화 한다.

shadow root 내부에 디스패치된 이벤트는 해당 shadow root 외부에 표시되지 않는다. 이벤트가 shadow dom 경계를 통과하도록 하려면 composed 프로퍼티를 true로 설정해야 한다. dom 트리의 모든 노드가 이벤트를 볼 수 있도록 composed 와 bubbles가 쌍을 이루는 것이 일반적이다.

예시 코드 아래 inging

Decorators

https://lit.dev/docs/components/decorators
데코레이터는 제안된 자바스크립트 기능이므로 데코레이터를 사용하려면 Babel이나 TypeScript와 같은 컴파일러를 사용해야 합니다.

license

  • https://www.olis.or.kr/license/Detailselect.do?lId=1092
  • 저작권자 표기. BSD 라이선스가 걸린 소프트웨어를 이용하는 경우, 해당 저작권자의 이름과 BSD 라이선스의 내용을 같이 배포해야 한다.
  • 보증 부인. BSD 라이선스가 걸린 소프트웨어로 인하여 법률상/도의상 피해가 발생하더라도, 그 책임을 저작권자에게 물을 수 없다.

Composition


LitElement 스타일 적용

lit-html + scss

2가지 방법
https://stackoverflow.com/questions/68988650/how-to-add-a-scss-stylesheet-to-a-lit-web-component

  1. lit-scss-loader
    1버전:webpack4, 2버전:webpack5
    A webpack loader that automatically generates the JavaScript style that is required for LitElement, simply by importing the CSS/SCSS file.
npm i -D lit-scss-loader extract-loader
module.exports = {
    entry: './src/index.js',
    module: {
        rules: [
            {
                test: /\.css|\.s(c|a)ss$/,
                use: [{
                    loader: 'lit-scss-loader',
                    options: {
                        minify: true, // defaults to false
                    },
                }, 'extract-loader', 'css-loader', 'sass-loader'],
            },
        ],
    },
};
  1. unsafeCSS
static get styles() {
    return css`${unsafeCSS(styles)}`;
}

공통 스타일 파일 분리
@use 사용
https://stackoverflow.com/questions/17598996/sass-use-variables-across-multiple-files

global/reset css 적용

결론: global, reset css 를 컴포넌트 마다의 스타일로 적용해줘야 함

https://stackoverflow.com/questions/57706814/lit-element-how-do-i-set-global-reset-css
LitElement는 기본적으로 외부 CSS가 구성 요소의 내부 트리에 영향을 미치지 않도록 설계된 Shadow DOM을 사용하기 때문에 예상대로 작동하지 않습니다.

web components 내부의 스타일에 영향을 미치는 유일한 방법은 components 가 CSS 변수를 사용하거나 스타일을 상속하는 속성이 web component 내부에서 정의되지 않은 경우입니다. ( lit docs - CSS inheritance )


lit-html + asset


Shadow DOM 없이 LitElement 생성하기

https://github.com/lit/lit/issues/1645 (21년 12월)

https://stackoverflow.com/questions/55126694/how-to-create-litelement-without-shadow-dom

createRenderRoot를 사용하면 섀도 루트를 생성하는 작업을 재정의할 수 있습니다. 일반적으로 라이트덤에 렌더링할 때 사용합니다.

createRenderRoot() {
  return this;
}

but 섀도 DOM을 사용하는 것을 정말 추천합니다.
요소가 light dom으로 덮어써지면 합성이 어렵습니다.

각 구성요소에 필요한 부품만 가져올 수 있도록 스타일시트를 세분화하는 것이 이상적입니다. 나는 그 부품들이 자동적으로 부품들과 함께 로드될 수 있도록 JS 모듈로 포장하고, 그것들을 shadow root 에 주입할 것이다.

createRenderRoot를 재정의하면 캡슐화된 CSS 및 슬롯과 같은 섀도 DOM 기능을 사용할 수 없게 됩니다. 그럼 웹 컴포넌트를 사용하는 의미는 무엇인가요?

웹 구성요소를 사용하면 코드를 구성요소화할 수 있습니다. 이는 아직 React/Vue/Angular 등을 사용하지 않는 경우 거의 항상 향상된 기능입니다. 여전히 캡슐화가 가능합니다. 또한, 이미 많은 CSS 규칙을 가진 거대한 코드 기반을 가지고 있다면, 조명이 켜진 CSS를 사용하기 위해 스타일을 변환하는 것이 어려울 수 있다. 그리고 섀도 DOM을 채택하는 것을 복잡하게 만드는 다른 많은 사소한 문제들이 있다. 우리는 이상적인 세계에 살고 있지 않다.

섀도 DOM이 없으면 web component가 아닌 custom element입니다.

슬롯은 그림자 영역에만 한정됩니까? 조명도 슬롯을 사용할 수 없나요?

<slot>은 섀도 DOM 기능입니다. 슬롯 개념이 작동하려면 투영된 콘텐츠와 투영할 지점을 분리해야 합니다. 섀도 DOM이 없는 DOM과 같은 하나의 컨텍스트에서만 작동하지 않습니다.

부트스트랩이나 다른 웹사이트 와이드 스타일시트를 어떻게 사용하는 것이 좋을까요? - 컴포넌트에 bootstrap을 연결해서 부트스트랩 shadow dom을 사용할 수 있음. 동일한 링크는 캐싱되므로 페이지 overload가 걸리지 않음


LitElement 이벤트 처리

앞서 만든 Web Component로 부터 이벤트에 따른 변화를 알아야 한다면 어떻게 해야 할까?

가련 버튼을 클릭한 이벤트의 횟수를 외부에서 알아야 한다면?https://enumclass.tistory.com/227

https://stackoverflow.com/questions/60022651/custom-element-custom-event-handler-attributes

https://javascript.works-hub.com/learn/web-components-api-lifecycle-events-and-custom-events-66668

https://www.raymondcamden.com/2022/10/10/working-with-custom-events-and-web-components

웹컴포넌트를 사용하는 곳에서 웹컴포넌트의 이벤트 수신하기

기타

런타임에도 필요하기때문에 dependencies 에 설치

https://medium.com/@mariusbongarts/build-your-own-blog-portfolio-with-web-components-lit-library-2701dffc735f

profile
하루 모아 평생 🧚🏻

0개의 댓글