将值传递给自定义HTMLElement的构造函数

时间:2019-04-08 21:14:46

标签: javascript django html5

我有一个自定义的HTMLElement,它可以按预期工作,但是我找不到将参数传递给构造函数的方法。相反,我正在访问传递自定义标记中的值,但是随后我不得不在https://source.unsplash.com/1600x900/?roblox中设置这些值,对此我不满意。

这是我现在正在做的基本版本:

connectedCallback()

我宁愿将videoId直接传递给构造函数,类似这样(不起作用):

JS:

class TrackingPreview extends HTMLElement {
  constructor() {
    super();

    const video = document.createElement('video');
    video.setAttribute('controls', '');
    video.setAttribute('width', '1920');
    video.setAttribute('height', '1080');
    shadow.appendChild(video);

    this.video = video;
  }

  connectedCallback() {
    const videoId = this.getAttribute('video-id');
    this.video.id = videoId;
  }
}

HTML页面上的JS脚本:

 class TrackingPreview extends HTMLElement {
  constructor(videoId) {
    super();

    const video = document.createElement('video');
    video.setAttribute('id', videoId);
    video.setAttribute('controls', '');
    video.setAttribute('width', '1920');
    video.setAttribute('height', '1080');
    shadow.appendChild(video);
  }

  connectedCallback() {
  }
}

是否可以将值传递给自定义构造函数?这些文档暗示有可能,但对如何做到却不是很有帮助。

3 个答案:

答案 0 :(得分:1)

请记住,常规HTML元素均不带有构造函数参数:不要依赖它们。取而代之的是,依靠具有JS属性支持的属性,并根据custom elements spec将其连接起来。

因此,以与Image的以下代码相同的方式:

let img = new Image();
img.src = "https://example.com/someimage.jpg";
img.width = ...
...

或脚本元素:

let script = document.createElement("script");
script.src = ...
// or script.textContent = ...

您的组件不需要构造函数属性。您将像这样使用它:

let preview = TrackingPreview();
preview.width = 1920;
preview.height = 1080;

或HTML格式

<track-preview width="100" height="200" ...></track-preview>

让您的自定义元素对设置的那些属性做出反应:

class TrackingPreview extends HTMLElement {

  static get observedAttributes() {
    return [`width`, `height`];
  }
  
  constructor() {
    super();
    const shadow = this.attachShadow({mode: 'open'});
    const video = this.video = document.createElement('video');
    video.setAttribute(`controls`, `controls`);
    video.setAttribute(`width`, this.getAttribute(`width`) || 1920);
    video.setAttribute(`height`, this.getAttribute(`height`) || 1080);
    shadow.appendChild(video);
  }

  get width() {
    return this.video.width;
  }

  set width(val) {
    this.setAttribute(`width`, val);
  }

  get height() {
    return this.video.height;
  }

  set height(val) {
    this.setAttribuite(`height`, val);
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === `width`) {
      this.video.width = newValue;
    }
    if (name === `height`) {
      this.video.height = newValue;
    }
    // ...
  }

  // ...
}

答案 1 :(得分:0)

您可以使用new关键字:

const tacking_preview = new TrackingPreview( id )

答案 2 :(得分:0)

Web组件的构造函数的规则非常严格。一个规则是不允许您将任何参数传递给构造函数。

https://w3c.github.io/webcomponents/spec/custom/#custom-element-conformance

请同时使用属性和属性

class TrackingPreview extends HTMLElement {
  static get observedAttributes() {
    return ['videoid'];
  }

  constructor() {
    super();

    const video = document.createElement('video');
    video.setAttribute('controls', '');
    video.width = 192;
    video.height = 108;
    this.video = video;
    this.attachShadow({mode: 'open'}).appendChild(video);
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    if (oldVal !== newVal) {
      this.video.setAttribute('id', newVal);
    }
  }
  
  get videoId() {
    return this.video.getAttribute('id');
  }

  set videoId(val) {
    if (val == null) { // check for null and undefined
      this.removeAttribute('videoid');
    }
    else {
      this.setAttribute('videoid', val);
    }
  }
}

customElements.define('tracking-preview', TrackingPreview);

setTimeout(function() {
  let el = document.querySelector('tracking-preview');
  if (el) {
    console.log(el.videoId);
    el.videoId = 99;
    console.log(el.videoId);
  }
}, 500);
<tracking-preview videoid="10"></tracking-preview>

设置属性videoid后,将调用attributeChangedCallback函数,并将该值向下传递到video元素。

在超时功能中,我同时读写videoId属性的videoid属性。