您所要求的通常是框架的工作。
最好通过属性而不是属性将对象传递给 Web 组件:
属性
var obj = { name: "John", age: 30, city: "New York" };
class TabelComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'}).innerHTML = '<h1>your DOM here</h1><pre id="content"></pre>';
}
connectedCallback() {
}
set content(val) {
this._content = val;
// render changes
let el = this.shadowRoot.querySelector('#content');
el.textContent = JSON.stringify(this._content,0,2);
}
get content() {
return this._content;
}
}
window.customElements.define('table-component', TabelComponent);
setTimeout(() => {
let el = document.getElementById('mine');
el.content = obj;
}, 10);
<table-component id="mine"></table-component>
数据 URI
但是,如果您真的想通过属性传递一些东西,那么请考虑使用数据 URI 的标准。 (https://devdocs.io/http/basics_of_http/data_uris)
这是通过始终使用fetch 来获取数据并将content 属性视为URL 来完成的。这允许您从 URL 加载数据,并且仍然允许您直接传入 JSON 数据。
您的数据确实需要完全符合 JSON 标准,并且还需要进行 URL 编码。
最简单的方法是使用observedAttributes 静态函数定义您要观看的属性,然后attributeChangedCallback 知道属性何时发生变化。请注意,当属性被删除时,newVal 将变为 null,您需要以不同方式处理它。
下面的例子很简单,需要一些错误检查。但它展示了如何使用数据 URI 来完成任务。
class TabelComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'}).innerHTML = '<h1>your DOM here</h1><pre id="content"></pre>';
}
static get observedAttributes() {
return ['content'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
if (newVal === null) {
// Attribute was removed
this._content = null;
this.render();
}
else {
fetch(newVal).then(
(res) => res.json()
).then(
(data) => {
this._content = data;
this.render();
}
);
}
}
}
connectedCallback() {
}
render() {
let el = this.shadowRoot.querySelector('#content');
el.textContent = JSON.stringify(this._content,0,2);
}
get content() {
return this._content;
}
}
window.customElements.define('table-component', TabelComponent);
setTimeout(() => {
let el = document.getElementById('mine');
el.content = obj;
}, 10);
<table-component content="data:application/json,%7B%22name%22%3A%22John%22%2C%22age%22%3A30%2C%22city%22%3A%22New%20York%22%7D" id="mine"></table-component>
属性中的 JSON
如果你真的不想使用完整的数据 URI,你可以将代码剪裁一点:
class TabelComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'}).innerHTML = '<h1>your DOM here</h1><pre id="content"></pre>';
}
static get observedAttributes() {
return ['content'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
if (newVal === null) {
// Attribute was removed
this._content = null;
this.render();
}
else {
console.log(newVal);
this._content = JSON.parse(newVal);
this.render();
}
}
}
connectedCallback() {
}
render() {
let el = this.shadowRoot.querySelector('#content');
el.textContent = JSON.stringify(this._content,0,2);
}
get content() {
return this._content;
}
}
window.customElements.define('table-component', TabelComponent);
<table-component content="{&quot;name&quot;:&quot;John&quot,&quot;age&quot;:30,&quot;city&quot;:&quot;New York&quot;}" id="mine"></table-component>
您可能会注意到,这确实需要您将双引号编码为 &quot; 以防止意外的属性值结束。
当然,您总是可以强制您的属性使用单引号,然后不需要转义双引号,但您需要转义任何单引号:
<table-component content='{"name":"John","age":30,"city":"New York"}' id="mine"></table-component>
属性中的变量值
我真正认为您所要求的是能够通过在属性中设置变量名称来将变量的值传递给组件:
<table-component content='<variable name>' id="mine"></table-component>
这是可以做到的,但你现在正在进入框架领域。
问题是那个变量的作用域是什么?是全球性的吗?是成员变量吗?是别的吗?
如果您只想使用全局变量,那么这很容易。 但非常有限!:
var obj = { name: "John", age: 30, city: "New York" };
class TabelComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'}).innerHTML = '<h1>your DOM here</h1><pre id="content"></pre>';
}
static get observedAttributes() {
return ['content'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (newVal === null) {
// Attribute was removed
this._content = null;
this.render();
}
else {
this._content = window[newVal];
this.render();
}
}
connectedCallback() {
}
render() {
let el = this.shadowRoot.querySelector('#content');
el.textContent = JSON.stringify(this._content,0,2);
}
get content() {
return this._content;
}
}
window.customElements.define('table-component', TabelComponent);
<table-component content="obj"></table-component>
当obj 的值发生变化时,这不会自动更新。要让组件重新读取变量,您需要更改属性的值。但这比仅设置属性要复杂。
多个属性
这里没有代码,但最简单的版本可能是创建多个属性,每个属性都会影响 DOM 的一部分。然后您可以在需要更改时设置每个属性,而不是一直重置所有内容。