你如何解耦 Web 组件?
How do you decouple Web Components?
我正在尝试使用纯 javascript Web 组件在无框架的情况下工作。我希望我的 Web 组件能够独立工作并在不同站点上使用,但我还希望两个组件能够进行通信。所以他们应该能够在不紧耦合的情况下进行通信。
我做 Angular 的时候,这很容易。我可以通过 HTML 属性将对象传递给组件,组件将它作为对象而不是字符串接收。但在纯 javascript 中,属性始终是字符串。传递对象或使 Web 组件相互感知并能够通信的正确方法是什么?
使用 Web 组件,您可以像您所说的那样通过属性传递对象,但您也可以使用方法传递对象,或者通过 属性(实际上是 setter 方法)传递对象。
<my-component id="comp1"></my-component>
...
var myObject = { y:1, y:2 }
comp1.value = myObject //via property
comp1.setValue( myObject ) //via method
这是一个包含两个本机 V1 Web 组件的示例应用程序。 <component-1>
可以与 <component-2>
对话,因为您向 <component-1>
提供了一个 ID,而该 ID 指的是在 <component-2>
.
上设置的 ID
这类似于 <label>
标签与其 for
属性的工作方式。
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>
只会与 <component-2>
对话,前提是存在具有通过其 link-id
属性提供给 <component-1>
的 ID 的组件。
我正在尝试使用纯 javascript Web 组件在无框架的情况下工作。我希望我的 Web 组件能够独立工作并在不同站点上使用,但我还希望两个组件能够进行通信。所以他们应该能够在不紧耦合的情况下进行通信。
我做 Angular 的时候,这很容易。我可以通过 HTML 属性将对象传递给组件,组件将它作为对象而不是字符串接收。但在纯 javascript 中,属性始终是字符串。传递对象或使 Web 组件相互感知并能够通信的正确方法是什么?
使用 Web 组件,您可以像您所说的那样通过属性传递对象,但您也可以使用方法传递对象,或者通过 属性(实际上是 setter 方法)传递对象。
<my-component id="comp1"></my-component>
...
var myObject = { y:1, y:2 }
comp1.value = myObject //via property
comp1.setValue( myObject ) //via method
这是一个包含两个本机 V1 Web 组件的示例应用程序。 <component-1>
可以与 <component-2>
对话,因为您向 <component-1>
提供了一个 ID,而该 ID 指的是在 <component-2>
.
这类似于 <label>
标签与其 for
属性的工作方式。
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>
只会与 <component-2>
对话,前提是存在具有通过其 link-id
属性提供给 <component-1>
的 ID 的组件。