How do you decouple Web Components?

浪尽此生 提交于 2019-12-20 02:47:44

问题


I'm trying to work frameworkless, with pure javascript Web Components. I want my Web Components to be able to work stand-alone and be used on different sites, and yet I also want two components to be able to communicate. So they should be able to communicate without being tightly coupled.

Back when I did Angular, this was easy. I can pass objects to a component through a HTML attribute, and the component receives it as an object rather than a string. But in pure javascript, attributes are always strings. What is the right way to pass objects around, or otherwise make Web Components aware of each other and able to communicate?


回答1:


Here is a sample app with two native V1 Web Components. <component-1> can talk to <component-2> because you supply an ID into <component-1> and that ID refers to the ID set on <component-2>.

This is similar to how the <label> tag work with its for attribute.

HTML

<component-1 link-id="c2"></component-1>
<hr/>
<component-2 id="c2"></component-2>

JS

// Class for `<component-1>`
class Component1 extends HTMLElement {
  constructor() {
    super();
    this._linkedComponent = null;
    this._input = document.createElement('input');
    this._input.addEventListener('focus', this._focusHandler.bind(this));

    this._button = document.createElement('button');
    this._button.textContent = 'Add';
    this._button.addEventListener('click', this._clickHandler.bind(this));
  }

  connectedCallback() {
    this.appendChild(this._input);
    this.appendChild(this._button);
  }

  static get observedAttributes() {
    return ['link-id'];
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    if (oldVal !== newVal) {
      if (newVal === null) {
        this._linkedComponent = null;
      }
      else {
        this._linkedComponent = document.getElementById(newVal);
      }
    }
  }

  _clickHandler() {
    if (this._linkedComponent) {
      this._linkedComponent.value = this._input.value;
    }
  }

  _focusHandler() {
    this._input.value = '';
  }
}

// Class for `<component-2>`
class Component2 extends HTMLElement {
  constructor() {
    super();
    this._textArea = document.createElement('textarea');
    this._textArea.setAttribute('style','width:100%;height:200px;');
  }

  connectedCallback() {
    this.appendChild(this._textArea);
  }

  set value(newValue) {
    this._textArea.value += (newValue+'\n');
  }
}

customElements.define('component-1', Component1);
customElements.define('component-2', Component2);

<component-1> will only talk to <component-2> if there is a component with the ID that was provided to <component-1> through its link-id attribute.




回答2:


With Web Components you can pass objects through attributes as you said, but you can also pass an object with a method, or throug a property (which is actually a setter method).

<my-component id="comp1"></my-component>
...
var myObject = { y:1, y:2 }
comp1.value = myObject     //via property
comp1.setValue( myObject ) //via method


来源:https://stackoverflow.com/questions/47510957/how-do-you-decouple-web-components

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!