Lit를 사용한 프레임워크 간 웹 구성 요소 라이브러리 📚(1부)
이 예에서는 내가 가장 좋아하는 패턴 라이브러리 중 하나인 Inclusive Components 소품에서 훌륭한 책으로 포팅하여 두 개의 카드 구성 요소를 만들 것입니다.
조명 사용
바닐라 Javascript로 웹 구성 요소를 생성, 크기 조정 및 유지 관리하면 빠르게 지저분해질 수 있으므로 Typescript를 사용하는 lit을 사용하여 표현력을 향상시키기로 했습니다.
어쨌든 웹 구성 요소 구현이 내부에서 어떻게 작동하는지 이해하기 위해 바닐라 JS 구현을 살펴보는 것을 잊지 않는 것이 가장 좋습니다.
이 문서link와 카드 요소의 원본 Html 및 Js 코드here에서 조명 문서를 찾을 수 있습니다.
자, 손을 더럽히자
link 에서 빈 git repo를 시작했습니다.
기여를 자유롭게 추가하고 개선 사항은 항상 환영합니다.
Typescript, Eslint, Jasmine 및 Open Web Components 라이브러리를 추가하여 모두 모범 코드 사례를 따르고 다음 이후에 구성 요소를 테스트했습니다.
내 폴더 구조는 공유 항목을 가질 수 있는 구성 요소 폴더가 됩니다.
이 경우 두 구성 요소 간에 일부 스타일을 공유합니다.
다음으로 웹 구성 요소 API에 액세스하기 위해 일부 메서드를 상속하고 캡슐화하는 @customElement ('card-image')
에서 확장되는 card.ts
의 새 클래스 데코레이터LitElement
를 만들기 시작합니다.
import { LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('card-image')
export class Card extends LitElement {}
구성 요소 속성을 전달하기 위해 인터페이스를 정의하기 시작한 후 동일한 파일에 선언했지만 재사용할 생각이 있다면 자유롭게 분리된 파일을 만들 수 있습니다.
...
export interface CardConfig {
altText: string;
ctaText: string;
image: string;
link: string;
text: string;
textDesc: string;
textDescLink: string;
title: string;
}
@customElement('card-image')
export class Card extends LitElement {}
렌더링 메서드에서 반환될 구성 개체와 Html을 정의할 시간입니다.
...
@customElement('card-image')
export class Card extends LitElement {
@property({ type: Object }) card!: CardConfig;
render() {
return html`
<li class="card">
<div class="img">
<img src="${this.card.image}" alt="${this.card.altText}" />
</div>
<div class="text">
<h2>
<a id="card-link" href="${this.card.link}" aria-describedby="desc-a-card"
>${this.card.title}</a
>
</h2>
<p>${this.card.text}</p>
<span class="cta" aria-hidden="true" id="desc-a-card">${this.card.ctaText}</span>
<small><a href="${this.card.textDescLink}">${this.card.textDesc}</a></small>
</div>
</li>
`;
}
}
이제 스타일을 정의할 수 있습니다. 또한 글꼴 정의인 공유 스타일을 가져옵니다.
...
import { sharedStyles } from './shared/style';
const componentStyle = css`
h2 {
margin-bottom: 1rem;
}
.card + .card {
margin-top: 1.5rem;
}
@supports (display: grid) {
.card + .card {
margin-top: 0;
}
}
.card {
cursor: pointer;
border: 1px solid;
border-radius: 0.25rem;
display: flex;
flex-direction: column;
position: relative;
}
.card .text {
padding: 1rem;
flex: 1 0 auto;
display: flex;
flex-direction: column;
cursor: pointer;
}
.card p {
max-width: 60ch;
}
.card .img {
height: 6.5rem;
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 calc(100% - 1rem));
}
.card .img img {
width: 100%;
height: 100%;
object-fit: cover;
filter: grayscale(100%);
}
.card a {
outline: none;
}
.card h2 a {
text-decoration: none;
}
.card h2 a:focus {
text-decoration: underline;
}
.card h2:focus-within ~ .cta {
box-shadow: 0 0 0 0.125rem;
}
.card:focus-within h2 a:focus {
text-decoration: none;
}
.card small {
display: block;
text-align: right;
}
.card small a {
position: relative;
text-decoration: none;
padding: 0.5rem 0;
}
.card small a:hover,
.card small a:focus {
text-decoration: underline;
}
.card .text > * + * {
margin-top: 0.75rem;
}
.card .text > :nth-last-child(3) {
margin-bottom: 0.75rem;
}
.card .text > :nth-last-child(2) {
margin-top: auto;
padding-top: 0.75rem;
}
.cta {
padding: 0.75rem;
border: 1px solid;
border-radius: 0.25rem;
text-align: center;
}
.cta > a {
text-decoration: none;
}
`;
@customElement('card-image')
export class Card extends LitElement {
static styles = [sharedStyles, componentStyle];
...
}
마지막으로 나열된 중복 클릭 이벤트 문제here를 해결하기 위해 두 개의 이벤트를 설정합니다.
...
@customElement('card-image')
export class Card extends LitElement {
...
@query('#card-link') cardLinkEl!: HTMLAnchorElement;
render() {
return html`
<li class="card">
<div class="img">
<img
src="${this.card.image}"
alt="${this.card.altText}"
@mousedown="${this.mouseDown}"
@mouseup="${this.handleClick}"
/>
</div>
<div class="text">
<h2>
<a
id="card-link"
href="${this.card.link}"
@mousedown="${this.mouseDown}"
@mouseup="${this.handleClick}"
aria-describedby="desc-a-card"
>${this.card.title}</a
>
</h2>
<p>${this.card.text}</p>
<span class="cta" aria-hidden="true" id="desc-a-card"
><a href="${this.card.link}">${this.card.ctaText}</a>
</span>
<small><a href="${this.card.textDescLink}">${this.card.textDesc}</a></small>
</div>
</li>
`;
}
mouseDown() {
this.down = Number(new Date());
}
handleClick() {
this.up = Number(new Date());
const total = this.up - this.down;
if (total < 200) {
this.cardLinkEl.click();
}
}
}
이제 다음과 같은 단일 카드 구성 요소가 있어야 합니다.
다음 부분에서는 이 구성요소를 테스트하고 원래 카드를 재사용하는 다른 구성요소를 테스트할 것입니다.
Reference
이 문제에 관하여(Lit를 사용한 프레임워크 간 웹 구성 요소 라이브러리 📚(1부)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/fstbraz/creating-a-cross-framework-components-library-with-web-components-using-lit-4doi텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)