웹 구성 요소를 통한 제품 카드 구성 요소

웹 구성 요소


우리는 웹 구성 요소를 이용하여 제품 카드 구성 요소를 만들 것이다.웹 구성 요소는 사용자 정의 UI 컨트롤을 만들 때 복잡한 HTML 코드를 봉인합니다.코드 충돌을 걱정할 필요 없이 세 가지 기술 (HTML, CSS, JavaScript) 을 사용하여 어디에서나 재사용할 수 있는 사용자 정의 요소를 만듭니다.

기초 지식


웹 구성 요소를 시작하기 위해 사용자 정의 요소를 만들어야 합니다.이를 위해, 우리는 원소를 지정하는 클래스나 함수를 만들었다.우리는 HTML Element 클래스를 확장한 ProductCardComponent라는 클래스를 만들 것입니다.
class ProductCardComponent extends HTMLElement{
    constructor(){
        super();
    }
}
...
사용자 정의 요소를 등록하기 위해 CustomElementRegistry를 사용합니다.define () 메서드.이 방법은 두 개의 매개 변수와 선택할 수 있는 매개 변수를 받아들인다.첫 번째 파라미터는 사용자 정의 요소의 이름으로 하이픈으로 구분된 문자열 (kebab 대소문자) 을 사용합니다. 이것은 단어가 될 수 없습니다.우리는 우리의 요소 제품 카드를 명명할 것이다.두 번째 매개 변수는 원소 행위를 정의하는 클래스나 함수의 이름입니다.
...
window.customElements.define('product-card', ProductCardComponent);

그림자 DOM


웹 구성 요소를 봉인하는 관건적인 부분 중 하나는 그림자 DOM이다.그림자 DOM은 숨겨진 분리 DOM을 요소에 추가하는 방법을 제공하여 구성 요소의 스타일, 구조, 동작이 페이지의 다른 코드와 충돌하지 않도록 합니다.
사용자 정의 요소에 그림자 DOM을 추가하기 위해 이 요소를 사용합니다.attachShadow() 메서드입니다.이것은 매개 변수와 키가 있는 대상이 필요합니다. 모드와value: "open"또는 "closed"입니다.Open을 사용하면 홈 페이지 컨텍스트에서 작성된 JavaScript를 사용하여 그림자 DOM에 액세스할 수 있습니다.
...
constructor(){
   super();
   this.attachShadow({mode: 'open'});
}
...
다음은 구성 요소의 구조를 포함하는 요소를 만듭니다.그런 다음 그림자 DOM에 요소를 추가합니다.
...
constructor(){
   super();
   this.template = document.createElement('template');
   this.template.innerHTML = ` `;

   this.attachShadow({mode: 'open'});
   this.shadowRoot.appendChild(this.template.content.cloneNode(true));
}
...
이것이 바로 설정입니다. 이제 우리는 우리의 구성 요소를 구축하기 시작할 수 있습니다.

제품 카드 구성 요소



제품 카드에 표시될 제품의 이미지가 표시됩니다.구성 요소의 사용자가 이 이미지의 원본을 설정할 수 있도록 허용해야 합니다.또한 기본 텍스트 영역 (제품 이름을 표시할 것), 하위 텍스트 영역 (제품 가격을 표시할 것) 과 단추가 있습니다. 사용자가 텍스트, 텍스트 색상, 배경색을 설정할 수 있도록 합니다.우리는 요소 속성에서 모든 요소에 값을 설정하고 innerHTML 설정 단추의 이름을 사용합니다.
<product-card img='./source.jpg' 
   main='Product Name' 
   sub-one='$10.00'
   button-color='orange'
   button-text-color='black'> Button Text </product-card>
그리고 구조 함수에 변수를 만들고 속성 값으로 설정합니다.
...
constructor(){
   super();
   this.template = document.createElement('template');

   this.main = this.getAttribute('main');
   this.img = this.getAttribute('img');
   this.subOne = this.getAttribute('sub-one');
   this.buttonColor = this.getAttribute('button-color');
   this.buttonTextColor = this.getAttribute('button-text-color');
   this.buttonText = this.innerHTML;

   this.template.innerHTML = ` 

   `;

   this.attachShadow({mode: 'open'});
   this.shadowRoot.appendChild(this.template.content.cloneNode(true));
}
...
다음은 문자열에 코드를 작성하고 템플릿에 분배함으로써 구성 요소를 구축하기 시작합니다.innerHTML.우리의 구성 요소는 두 개의 메인 블록으로 구성되어 있기 때문에, 두 개의 div를 만들어서 이 블록을 표시하고, 그것을 하나의 용기 div에 포장할 것입니다. 우리는 용기 div에 하나의 클래스 카드cont, 두 개의 포장된 div 클래스 이름인imgcont와 info-cont를 만들 것입니다. 그리고,imgcont div에 하나의 img요소를 만들고, infocont div에 몇 개의 div 요소를 만들어서 메인 텍스트, 하위 텍스트, 단추를 포함합니다.앞에서 만든 변수를 사용하면img 요소에 src 속성을 입력하고 메인 텍스트, 하위 텍스트와 단추 텍스트를 입력합니다
...
   this.template.innerHTML = `
   <div class='card-cont'>
      <div class='img-cont'>
         <img src='${this.img}' alt='${this.main}'/>
      </div>
      <div class='info-cont'>
         <div class='top-info-cont'>
            <div class='main-cont'><p>${this.main}<p></div>
            <div class='sub1-cont'><p>${this.subOne}<p></div>
         </div>
         <div class='bottom-button-cont'>
            <button>${this.buttonText}</button>
         </div>
      </div>
   </div>
`
...
현재, 구성 요소의 스타일을 설정하기 위해서, 카드contdiv의 바로 위에 스타일 요소를 추가합니다.
...
   this.template.innerHTML =`
   <style>
   </style>
   <div class='card-cont'>
      ...
   </div>
`
...

버튼 및 컨테이너 스타일
...
this.template.innerHTML= `
      <style>
         button{
             min-width: 7rem;
             height: 1.8rem;
             opacity: 0;
             transition: 100ms ease 0s;
             border-radius: .5rem;
             border: none;
             background-color: ${this.buttonColor} ;
             font-weight: 300;
             font-size: .7rem;
             color: ${this.buttonTextColor};
         }
         img{
             width: 100%;
             min-height: 100%;
         }
         .card-cont{
             font-family: Segoe UI, sans-serif;
             font-size: .98rem;
             position: relative;
             background-color: none;
             width: 16.3rem;
             height: 16rem;
             transition: 500ms;
             color: white;
         }
         .img-cont{
             background-color: grey;
             width: 15rem;
             height: 15rem;
             transition: 500ms;
             overflow: hidden;
         }
         .info-cont{
             position: absolute;
             background-color: black;
             width: 11.8rem;
             height: 1.2rem;
             top: 13.75rem;
             left: 2.5rem;
             border-radius: .6rem;
             transition: height 500ms;
             padding: .5rem 1rem;
             box-shadow: 0px 0px 8px rgba(1,1,1,.3);
         }
         .top-info-cont{
             display: flex;
             justify-content: center;
             min-height: 50%;
             width: 100%;
         }
         .bottom-button-cont{
             display: flex;
             justify-content: center;
             align-items: center;
             height: 50%;
             width: 100%;
         }
         .main-cont{
             display: flex;
             flex-wrap: nowrap;
             font-weight: 700;
             text-align: left;
             width: 70%;

         }
         .sub1-cont{
             font-size: .8rem;
             text-align: right;
             width: 30%;

         }
      ...
      </style>
...
`

애니메이션 및 상호 작용 스타일
...
this.template.innerHTML =`
         ...
            .card-cont:hover{
                transform: scale(1.05,1.05);
                z-index: 100;
            }
            .card-cont:hover > .img-cont{
                border-radius: 1rem;
                box-shadow: 30px 30px 50px rgba(1,1,1,.3);
            }
            .card-cont:hover > .info-cont{
                height: 5.5rem;
                box-shadow: 30px 30px 50px rgba(1,1,1,.3);
            }
            .card-cont:hover top-info-cont{
                height: 50%;
            }
            .card-cont:hover button{
                opacity: 1;
                transition: 500ms ease-in 0s;
            }
            button:active{
                transform: scale(1.1,1.1);
            }
            .card-cont:focus{
                outline: 1px solid black;
                outline-offset: .5rem;
            }
         ...
`
...
이것은 우리의 카드 구성 요소를 완성할 것이다.

엑스트라


여기에는 서로 다른 수정이 있습니다. 우리는 우리가 아직 토론하지 않은 다른 웹 구성 요소 기능을 사용하여 우리의 구성 요소를 수정할 수 있습니다.

사용자 정의 이벤트


구성 요소 사용자가 웹 구성 요소의 단추를 언제 눌렀는지 알 수 있도록 사용자 정의 이벤트를 만들고 이벤트 탐지기를 실행할 수 있습니다.우선, 우리는 elements 클래스에서 방법을 만들고 이를 buttonClicked라고 부른다.이 방법에서, 우리는 Custom Event () 구조 함수를 사용하여 새로운 사용자 정의 이벤트를 만들고 이를 상수로 명명된 이벤트에 분배합니다.사용자 정의 이벤트는 두 개의 인자가 있습니다. 첫 번째는 이벤트 이름을 나타내는 문자열이고, 두 번째 (선택 사항) 는 임의의 값을 가진 키 "detail"의 대상입니다.자세한 정보는 이벤트 탐지기에 전달하고자 하는 모든 데이터를 포함할 수 있습니다.그리고 우리는 사건을 스케줄링할 방법이 있다.
...
   buttonClicked(){
      const event = new CustomEvent('',{
         detail:{
            id:this.id
         }
      });
      document.dispatchEvent(event);
   }
...

웹 구성 요소:connectedCallback 및disconnectedCallback


사용자 정의 요소가 문서 DOM에 처음 연결되면 connectedCallback이 호출됩니다.disconnectedCallback은 문서 DOM과 연결을 끊을 때 호출됩니다.이벤트 탐지기를'클릭'구성 요소 단추로 실행하고, 디스카운트 탐지기를 사용하여 이벤트 탐지기를 삭제합니다.
...
connectedCallback() {
   this.shadowRoot.querySelector('button').addEventListener('click', () => this.buttonClicked());
   }
disconnectedCallback() {
   this.shadowRoot.querySelector('button').removeEventListener();
   }
...

웹 구성 요소:슬롯


slot 요소는 자리 표시자입니다. 자신의 태그로 채울 수 있습니다.개별 Dom 트리를 작성하여 함께 표시할 수 있습니다.아래쪽 단추 용기div의 단추를 제거하고slot 요소로 대체합니다.그리고 우리는 우리의 요소 innerHTML을 slot 요소에 삽입할 것입니다.이것은 웹 구성 요소의 사용자가 구성 요소의 정보 제어 영역에 자신의 표시를 넣을 수 있도록 합니다.
this.main = this.getAttribute('main');
   this.img = this.getAttribute('img');
   this.subOne = this.getAttribute('sub-one');
   this.buttonColor = this.getAttribute('button-color');
   this.buttonTextColor = this.getAttribute('button-text-color');
   this.userMrkUp = this.innerHTML;

   this.template.innerHTML = `
...
   <div class='card-cont'>
      <div class='img-cont'>
         <img src='${this.img}' alt='${this.main}'/>
      </div>
      <div class='info-cont'>
         <div class='top-info-cont'>
            <div class='main-cont'><p>${this.main}<p></div>
            <div class='sub1-cont'><p>${this.subOne}<p></div>
         </div>
         <div class='bottom-button-cont'>
            <slot>${this.userMrkUp}</slot>
         </div>
      </div>
   </div>
`
...
Code

좋은 웹페이지 즐겨찾기