如何将对象(或关联数组)作为属性值传递给我的 Web 组件

Hus*_*hid 6 html javascript object web-component

我正在制作 vanilla-js 网络组件,需要将对象作为其值传递给属性,但每次都将其作为字符串。

我能够将字符串传递给组件的属性,但我知道我需要传递一个对象。

var obj = { name: "John", age: 30, city: "New York" };

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

class TabelComponent extends HTMLElement {

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

    connectedCallback() {
        console.log(this.content);
    }
    
    get content() {
        return this.getAttribute("content")
    }
}

window.customElements.define('table-component', TabelComponent);
Run Code Online (Sandbox Code Playgroud)
<table-component content=obj></table-component>
Run Code Online (Sandbox Code Playgroud)

我的属性“内容”应该将 obj 作为对象而不是字符串。我应该进入 { name: "John", age: 30, city: "New York" };控制台

Int*_*lia 5

您要求的通常是框架的工作。

最好通过属性而不是属性将对象传递给 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);
Run Code Online (Sandbox Code Playgroud)
<table-component id="mine"></table-component>
Run Code Online (Sandbox Code Playgroud)

数据URI

但是,如果您真的想通过属性传递某些内容,请查看使用数据 URI 的标准。(https://devdocs.io/http/basics_of_http/data_uris

这是通过始终使用fetch来获取数据并将content属性视为URL 来完成的。这允许您从 URL 加载数据,并且仍然允许您直接传入 JSON 数据。

您的数据确实需要完全符合 JSON 并且还需要进行 URL 编码。

最简单的方法是使用observedAttributes静态函数来定义您要监视的属性,然后attributeChangedCallback知道该属性何时发生变化。请注意,newValnull当属性被删除,你需要处理的是不同的。

下面的例子很简单,需要一些错误检查。但它展示了如何使用数据 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);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)
<table-component content="{&quot;name&quot;:&quot;John&quot,&quot;age&quot;:30,&quot;city&quot;:&quot;New York&quot;}" id="mine"></table-component>
Run Code Online (Sandbox Code Playgroud)

您可能会注意到,这确实需要您将双引号编码成&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);
Run Code Online (Sandbox Code Playgroud)
<table-component content="obj"></table-component>
Run Code Online (Sandbox Code Playgroud)

当值obj更改时,这不会自动更新。要让组件重新读取变量,您需要更改属性的值。但这比设置属性更复杂。

多重属性

这里没有代码,但最简单的版本可能是创建多个属性,每个属性都会影响 DOM 的一部分。然后您可以在需要更改时设置每个属性,而不是一直重置所有内容。


NiZ*_*iZa 0

您可以将对象解析为 JSON 字符串,例如:

var obj = { name: "John", age: 30, city: "New York" };
var objString = JSON.stringify(obj);
Run Code Online (Sandbox Code Playgroud)
<table-component id="h" content="objString "></table-component>
Run Code Online (Sandbox Code Playgroud)

然后在你的网络组件中应该将它解析回你的对象

var obj = JSON.parse(this.content);
Run Code Online (Sandbox Code Playgroud)