programing

웹 컴포넌트, 데이터 송수신

oldcodes 2023. 3. 25. 11:53
반응형

웹 컴포넌트, 데이터 송수신

데이터는 속성을 통해 커스텀html 요소로 전달되고 CustomEvent를 디스패치하여 전송됩니다.

JavaScript 객체는 이벤트 세부사항 필드에서 전송될 수 있지만 요소가 많은 데이터를 전달해야 한다면 어떻게 해야 할까요?JavaScript에서 오브젝트와 함께 제공하는 방법이 있습니까?

예를 들어 요소에 초기화 또는 동적으로 변경해야 하는 가변 개수의 부품이 포함되어 있는 경우(예: 가변 개수의 행이 있는 테이블)는 어떻게 됩니까?컴포넌트 내에서 해석되는 JSON 문자열로 구성된 Atribute의 설정 및 변경은 상상할 수 있지만, 이 Atribute는 우아하게 진행되지 않습니다.

<my-element tableRowProperties="[{p1:'v1', p2:'v2'}, {p1:'v1',p2:'v2'}, {p1:'v1',p2:'v2'}]"></my-element>

또는 요소가 데이터의 payload를 포함하는 외부 이벤트를 수신하도록 할 수 있습니까?

데이터 전송

컴포넌트에 대량의 데이터를 전달할 필요가 있는 경우는, 다음의 4개의 방법으로 실시할 수 있습니다.

1) 속성을 사용합니다.이것은 다음과 같이 요소에 값을 지정함으로써 객체를 전달하기 때문에 가장 간단합니다.el.data = myObj;

2) 속성을 사용합니다.개인적으로 이런 방식은 싫지만 일부 프레임워크에서는 속성을 통해 데이터를 전달해야 합니다.이것은 질문의 내용과 비슷합니다. <my-el data="[{a:1},{a:2}....]"></my-el>. 속성값 이스케이프와 관련된 규칙을 따르십시오.이 방법을 사용하는 경우,JSON.parse실패할 수 있습니다.또한 HTML에서 매우 추악해져서 속성으로 대량의 데이터를 표시할 수 있습니다.

3 자녀 요소를 통해 전달합니다.생각해 보세요<select>「」가 붙은 <option>라도 할 수 실제 일 필요도 없습니다.모든 요소 유형을 자녀로 사용할 수 있으며 실제 요소일 필요도 없습니다.고객님의 고객명connectedCallback이 함수는 코드상에서 모든 어린이를 잡아 요소, 속성 또는 콘텐츠를 컴포넌트에 필요한 데이터로 변환합니다.

4 [Fetch]사용합니다.요소가 자체 데이터를 가져올 수 있도록 URL을 제공합니다.을 생각하다<img src="imageUrl.png"/>컴포넌트용 데이터가 이미 있는 경우 이 옵션은 적절하지 않을 수 있습니다.그러나 브라우저는 위의 옵션 2와 비슷하지만 브라우저에 의해 자동으로 처리되는 내장 데이터의 쿨한 기능을 제공합니다.

다음은 이미지에 포함된 데이터를 사용하는 예입니다.

img {
  height: 32px;
  width: 32px;
}
<img src="data:image/svg+xml;charset=utf8,%3C?xml version='1.0' encoding='utf-8'?%3E%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 314.7 314.7'%3E%3Cstyle type='text/css'%3E .st0{fill:transparent;stroke:%23231F20;stroke-width:12;} .st1{fill:%23231F20;stroke:%23231F20;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:10;} %3C/style%3E%3Cg%3E%3Ccircle class='st0' cx='157.3' cy='157.3' r='150.4'/%3E%3Cpolygon class='st1' points='108,76.1 248.7,157.3 108,238.6'/%3E%3C/g%3E%3C/svg%3E">

다음은 웹 컴포넌트에 내장된 데이터를 사용하는 예입니다.

function readSrc(el, url) {
    var fetchHeaders = new Headers({
      Accept: 'application/json'
    });

    var fetchOptions = {
      cache: 'default',
      headers: fetchHeaders,
      method: 'GET',
      mode: 'cors'
    };

    return fetch(url, fetchOptions).then(
      (resp) => {
        if (resp.ok) {
          return resp.json();
        }
        else {
          return {
            error: true,
            status: resp.status
          }
        }
      }
    ).catch(
      (err) => {
        console.error(err);
      }
    );
  }

  class MyEl extends HTMLElement {
    static get observedAttributes() {
      return ['src'];
    }

    attributeChangedCallback(attrName, oldVal, newVal) {
      if (oldVal !== newVal) {
        this.innerHtml = '';
        readSrc(this, newVal).then(
          data => {
            this.innerHTML = `<pre>
${JSON.stringify(data,0,2)}
            </pre>`;
          }
        );
      }
    }
  }

  // Define our web component
  customElements.define('my-el', MyEl);
<!--
This component would go load its own data from "data.json"
<my-el src="data.json"></my-el>
<hr/>
The next component uses embedded data but still calls fetch as if it were a URL.
-->
<my-el src="data:json,[{&quot;a&quot;:9},{&quot;a&quot;:8},{&quot;a&quot;:7}]"></my-el>

XHR을 사용하여 동일한 작업을 수행할 수 있지만 브라우저가 웹 구성요소를 지원하는 경우 가져오기를 지원할 수 있습니다.그리고 만약 당신이 정말로 필요하다면 몇 가지 좋은 폴리 매립지가 있다.

옵션 4를 사용하는 가장 큰 장점은 URL에서 데이터를 가져와 데이터를 직접 삽입할 수 있다는 것입니다.그리고 이것이 바로 대부분의 미리 정의된 HTML 요소입니다.<img>을 하다

갱신하다

JSON 데이터를 오브젝트로 가져오는 다섯 번째 방법을 생각해 냈습니다., 「」, 「」를 합니다.<template>태그를 지정합니다. 전화는 했어요.JSON.parseJSON을 벗어날 필요가 없기 때문에 코드를 삭제할 수 있습니다.

class MyEl extends HTMLElement {
  connectedCallback() {
    var data;
    
    try {
      data = JSON.parse(this.children[0].content.textContent);
    }
    
    catch(ex) {
      console.error(ex);
    }

    this.innerHTML = '';
    var pre = document.createElement('pre');
    pre.textContent = JSON.stringify(data,0,2);
    this.appendChild(pre);
  }
}

// Define our web component
customElements.define('my-el', MyEl);
<my-el>
  <template>[{"a":1},{"b":"&lt;b>Hi!&lt;/b>"},{"c":"&lt;/template>"}]</template>
</my-el>

데이터 전송

컴포넌트로부터 데이터를 취득하는 방법에는, 다음의 3가지가 있습니다.

1) 속성에서 값을 읽습니다.속성은 모든 것이 될 수 있고 일반적으로 원하는 데이터 형식이기 때문에 이상적입니다.속성은 문자열, 개체, 숫자 등을 반환할 수 있습니다.

2) 속성을 읽습니다.이를 위해서는 컴포넌트가 Atribut을 최신 상태로 유지해야 하며 모든 Atribut이 문자열이기 때문에 최적의 상태가 아닐 수 있습니다. 때문에 가 전화할 합니다.JSON.parse당신의 가치를 믿거나 말거나.

3) 이벤트이것은 컴포넌트에 추가하는 가장 중요한 것입니다.이벤트는 컴포넌트의 상태가 변경되었을 때 트리거해야 합니다.이벤트는 사용자 상호 작용에 따라 트리거해야 하며, 사용자에게 어떤 일이 발생했거나 사용 가능한 상태임을 경고해야 합니다.기존에는 관련 데이터를 이벤트에 포함했습니다.이렇게 하면 컴포넌트 사용자가 작성해야 하는 코드의 양이 줄어듭니다.예, 여전히 속성이나 속성을 읽을 수 있지만 이벤트에 모든 관련 데이터가 포함되어 있으면 추가 작업을 수행할 필요가 없습니다.

의 @하지만 @Intervalia를 하는 여섯 .<script> 꼬리표 <template>붙이다

이것은 Markdown 요소에서 사용하는 것과 동일한 접근법입니다.

class MyEl extends HTMLElement {
  connectedCallback() {
    var data;
    
    try {
      data = JSON.parse(this.children[0].innerHTML);
    }
    
    catch(ex) {
      console.error(ex);
    }

    this.innerHTML = '';
    var pre = document.createElement('pre');
    pre.textContent = JSON.stringify(data,0,2);
    this.appendChild(pre);
  }
}

// Define our web component
customElements.define('my-el', MyEl);
<my-el>
  <script type="application/json">[{"a":1},{"b":"<b>Hi!</b>"},{"c":"</template>"}]</script>
</my-el>

폴리머 기반의 웹 컴포넌트를 사용하는 경우 데이터 바인딩을 통해 데이터를 전달할 수 있습니다.데이터는 속성의 JSON 문자열로 저장하여 컨텍스트 변수를 통해 전달할 수 있습니다.

<p>JSON Data passed via HTML attribute into context variable of  and populating the variable into combobox.</p> 
<dom-bind><template>
<iron-ajax url='data:text/json;charset=utf-8,
                [{"label": "Hydrogen", "value": "H"}
                ,{"label": "Oxygen"  , "value": "O"}
                ,{"label": "Carbon"  , "value": "C"}
                ]'
           last-response="{{lifeElements}}" auto handle-as="json"></iron-ajax>
<vaadin-combo-box id="cbDemo"
        label="Label, value:[[cbDemoValue]]"
        placeholder="Placeholder"
        items="[[lifeElements]]"
        value="{{ cbDemoValue }}"
>
    <template>
        [[index]]: [[item.label]] <b>[[item.value]]</b>
    </template>
</vaadin-combo-box>
<vaadin-combo-box label="Disabled" disabled value="H" items="[[lifeElements]]"></vaadin-combo-box>
<vaadin-combo-box label="Read-only" readonly value="O" items="[[lifeElements]]"></vaadin-combo-box>   



<web-elemens-loader selection="
@polymer/iron-ajax,
@vaadin/vaadin-element-mixin/vaadin-element-mixin,
@vaadin/vaadin-combo-box,
"></web-elemens-loader>
</template></dom-bind>
<script src="https://cdn.xml4jquery.com/web-elements-loader/build/esm-unbundled/node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script><script type="module" src="https://cdn.xml4jquery.com/web-elements-loader/build/esm-unbundled/src/web-elemens-loader.js"></script>

Lego와 같은 작은 lib를 사용하면 다음과 같이 쓸 수 있습니다.

<my-element :tableRowProperties="[{p1:'v1', p2:'v2'}, {p1:'v1',p2:'v2'}, {p1:'v1',p2:'v2'}]"></my-element>

my-bycloss.web 컴포넌트 내에는 다음과 같은 것이 있습니다.

<template>
  <table>
    <tr :for="row in state.tableRowProperties">
      <td>${row.p1}</td>
      <td>${row.p2}</td>
    </tr>
</template>

<script>
  this.init() {
    this.state = { tableRowPropoerties: [] }
  }
</script>

이미 해결이 된 건 알지만, 여기 제가 취한 방법이 있습니다.나는 이것이 로켓 과학이 아니라는 것을 알고 있고 아마도 이런 식으로 하지 않을 이유가 있을 것이다. 하지만, 이것은 나에게 매우 효과가 있었다.

이는 한 번 사용할 수 있는 '키'인 사용자 지정 요소에 wc_data라는 속성이 전달되는 데이터를 전달하기 위한 간접적인 접근법입니다.

콜백이나 「콜인」등의 wc데이터를 커스텀 태그에 넣는 것으로, 어떠한 조작도 할 수 있습니다.

코드 및 상자에 연결

파일:

wc_data.ts

export const wc_data: {
    [name: string]: any,
    get(key: string): any,
    set(key: string, wc_data: any): any
} = {

    get(key: string): any {
        const wc_data = this[key];
        delete this[key];
        return wc_data;
    },

    set(p_key: string, wc_data: any) {
        this[p_key] = wc_data;
    }

}

커스텀 태그

import { wc_data } from './wc_data';

const template = document.createElement('template');

template.innerHTML = `

    <style>
        .custom-tag {
            font-size: 1.6em;
        }
    </style>

    <button class="custom-tag">Hello <span name="name"></span>, I am your <span name="relation"></span></button>
`;

class CustomTag extends HTMLElement {

    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.appendChild(template.content.cloneNode(true));
    }

    callin() {
        console.log('callin called');
    }

    connectedCallback() {
        const v_wc_data = wc_data.get(this.getAttribute('wc-data'));
        console.log('wc_data', v_wc_data);

        const v_name = this.shadowRoot.querySelector('[name="name"]');
        const v_relation = this.shadowRoot.querySelector('[name="relation"]');

        v_name.innerHTML = v_wc_data.name;
        v_relation.innerHTML = v_wc_data.relation;

        const v_button = this.shadowRoot.querySelector('button');

        v_button.style.color = v_wc_data.color;

        v_wc_data.element = this;

        v_button.addEventListener('click', () => v_wc_data.callback?.());

    }

    disconnectedCallback() {
    }
}

window.customElements.define('custom-tag', CustomTag);

console.log('created custom-tag element');

export default {};

SomeTsFile.ts

wc_data.set('tq', {
    name: 'Luke',
    relation: 'father',
    color: 'blue',
    element: undefined,
    callback() {
        console.log('the callback worked');
        const v_tq_element = this.element;
        console.log(this.element);
        v_tq_element.callin();
    },
});

일부 html..

<div>stuff before..</div>

<custom-tag wc_data="tq" />

<div>stuff after...</div>

다른 기여자들 덕분에, 저는 다소 간단한 해결책을 생각해냈습니다.json 해석 없음.이 예에서는 블록을 클릭할 수 있도록 컴포넌트 전체를 a-href로 랩합니다.


  customElements.define('ish-marker', class extends HTMLElement {
    constructor() {
      super()
      const template = document.getElementById('ish-marker-tmpl').content

      const wrapper = document.createElement("a")
      wrapper.appendChild( template.cloneNode(true) )
      wrapper.setAttribute('href', this.getAttribute('href'))

      const shadowRoot = this.attachShadow({mode: 'open'}).appendChild( wrapper )
    }
  })


<ish-marker href="https://go-here.com">
  ...
  // other things, images, buttons.
  <span slot='label'>Click here to go-here</span>
</ish-marker>

언급URL : https://stackoverflow.com/questions/50404970/web-components-pass-data-to-and-from

반응형