보너스: 웹 구성 요소로 Vue에서 문제 해결

이것은 웹 구성 요소를 다루고 있는 시리즈의 보너스 게시물입니다.




  • Polymer 라이브러리의 파트 4가 진행 중입니다. 기다리는 동안 웹 표준으로 해결할 수 있는 한 학생이 나에게 접근한 이 깔끔한 문제를 확인하십시오.

    그들은 라이브러리를 사용하여 Vue 구성 요소 내에서 WebGL 지구본을 렌더링했습니다. 그들은 일련의 마커를 생성한 다음 어떤 마커가 열리고 닫혔는지 추적하기를 원했습니다. WebGL 라이브러리는 각 마커의 팝업에 innerHTML 문자열을 첨부하기 위한 일부 API를 제공했지만 열기, 닫기 또는 클릭 이벤트를 추적하기 위한 API를 노출하지 않았습니다.

    약간의 악마적인 생각이 들었습니다😈. 라이브러리 팝업에 동작을 추가할 수 없지만 HTML을 추가할 수 있다면 자체 동작을 캡슐화하는 HTML을 추가하면 어떻게 될까요?

    🎩 구출하는 웹 구성 요소!! 👨‍💻

    <팝업 툴팁> 정의



    우리에게 필요한 것은 팝업이 열리거나 닫힐 때마다 이벤트를 발생시키는 HTML 요소였습니다. 팝업을 열고 닫는 데 사용되는 WebGL libstyle="visibility: visible"이므로 자체 부모를 관찰하기 위해 MutationObserver를 사용하는 요소를 생성합니다.

    class PopupTooltip extends HTMLElement {
      constructor() {
        super();
        this.observerCallback = this.observerCallback.bind(this);
        this.attachShadow({mode: 'open'});
        this.shadowRoot.appendChild(document.createElement('slot'));
        this.observer = new MutationObserver(this.observerCallback);
      }
    
      connectedCallback() {
        // HACK: WebGL library toggles style.visibility on it's own
        // generated DOM to hide and show tooltips.
        const libraryContainer = this.parentElement.parentElement.parentElement;
        const config = { attributes: true, subtree: false, children: false };
        this.observer.observe(libraryContainer, config);
      }
    
      observerCallback([{target}]) {
        const visible = target.style.visibility === 'visible';
        const type = 'popup-' + visible ? 'opened' : 'closed';
        const bubbles = true;
        const composed = true;
        const detail = this;
        this.dispatchEvent(new CustomEvent(type, { bubbles, composed, detail }));
      }
    }
    
    customElements.define('popup-tooltip', PopupTooltip);
    


    Vue 래퍼에 연결



    이제 컨테이너의 가시성이 WebGL 라이브러리에 의해 토글될 때마다 <popup-tooltip> 또는 popup-opened 이벤트를 발생시키는 popup-closed 요소가 있습니다. 래핑 Vue 구성 요소의 개인 DOM에 수신기를 설정합니다.

    <!-- WebGL lib instanciates on '#earth' -->
    <div id="earth" @popup-opened="onPopupOpened" @popup-closed="onPopupClosed"></div>
    


    각 팝업 만들기



    그런 다음 WebGL lib를 인스턴스화하고 데이터를 전달할 때 툴팁 콘텐츠에 <popup-tooltip> 요소를 표시하도록 마커를 설정했습니다.

    geoMarkers.forEach(marker => {
      const location = marker.latLng;
      const glMarker = new WebGLLib.popup({/*...*/});
      // NB: popupHTML is **just HTML**, there's no framework or library here.
      const popupHTML = `<popup-tooltip data-location="${location}">${marker.title}</popup-tooltip>`;
      // `bindPopup` is a method on our WebGL library's marker API.
      glMarker.bindPopup(popupHTML, config);
    })
    


    이익!



    마지막으로 해야 할 일은 어떤 팝업이 열리고 닫히는지 추적하는 것이었습니다.

    onPopupOpened({target: {dataset: {location}}}) {
      const [lat, lng] = location.split(',');
      console.log(`opened: lat: ${lat} lng: ${lng}`);
    }
    


    웹 구성 요소를 사용하기 위해 프레임워크를 포기할 필요가 없습니다. HTML 및 JavaScript를 사용할 수 있는 모든 곳에서 사용할 수 있습니다. 그것이 바로 여기에서 웹 구성 요소를 승리로 만든 것입니다. 우리의 GL 라이브러리는 Vue 구성 요소를 입력으로 사용하지 않고 HTML 문자열을 사용했습니다.

    폴리머 라이브러리의 파트 4에서 며칠 후에 뵙겠습니다.

    여기에서 다루는 주제에 대한 일대일 멘토링 세션을 원하십니까?

    좋은 웹페이지 즐겨찾기