在定义后修改自定义元素类

jam*_*ack 6 html javascript dom web-component custom-element

注册后是否可以修改自定义元素/Web 组件类?这不是我通常(或永远)想要在生产代码中做的事情,但是在原型设计或实现用于开发的代码修补工具时,它会很有用。到目前为止,这是我尝试过但未成功的方法:

document.body.appendChild(document.createElement('foo-bar')) // empty element

class FooBar extends HTMLElement {
  connectedCallback () {
    this.textContent = 'foo bar'
  }
}

customElements.define('foo-bar', FooBar) // element shows "foo bar"

FooBar.protoype.connectedCallback = function () {
  this.textContent = 'foo bar 2'
}

document.body.appendChild(document.createElement('foo-bar')) // element shows "foo bar", not "foo bar 2"

customElements.get('foo-bar').protoype.connectedCallback = function () {
  this.textContent = 'foo bar 2'
}

document.body.appendChild(document.createElement('foo-bar')) // element shows "foo bar", not "foo bar 2"

class FooBar2 extends HTMLElement {
  connectedCallback () {
    this.textContent = 'foo bar 2'
  }
}

customElements.define('foo-bar', FooBar2) // Exception thrown, 'foo-bar' already defined
Run Code Online (Sandbox Code Playgroud)

总之,修改最初传递给 CustomElementsRegistry 的类没有任何效果。分配给注册表中内容的原型无效。尝试为注册表中的元素分配新类是不可能的,因为会引发异常。所有这三种行为都与我在几乎所有其他 JavaScript API 的每个方面的经验背道而驰。无论好坏,除非将某些内容设置为不可配置,否则无法对其进行变异是非常不寻常的。但是,当我检查对象是否可配置时,运行时说它们是可配置的!

有没有人知道在定义自定义元素定义后修改/增强它的方法?

Jos*_*Lin 0

我认为改变标签的行为是很困难的,他们(浏览器开发人员)可能认为一个标签应该只定义一次。

我测试了修改影子根,它有效,如果你想模板化你的自定义标签,影子根会有所帮助。

let customTable = document.registerElement('custom-table', {
  prototype: Object.create(HTMLElement.prototype, {
    createdCallback: {
      value: function() {
        let shadowRoot = this.createShadowRoot();
        window.shadowRoot = shadowRoot
        let template = document.querySelector('#custom-table');
        shadowRoot.appendChild(template.content.cloneNode(true));
      }
    }
  })
});

let i = 0
setInterval(() => {
  shadowRoot.append(`${i++}s past `)
}, 1000)
Run Code Online (Sandbox Code Playgroud)
table {
  height: 100px;
  width: 100px;
  background-color: black;
}
Run Code Online (Sandbox Code Playgroud)
<template id="custom-table">
  <style>
    table {
    }
  </style>
  <table>
    <thead>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>P</td>
        <td>P</td>
        <td>A</td>
        <td>P</td>
      </tr>
    </tbody>
  </table>
</template>
<custom-table></custom-table>
<table>
</table>
Run Code Online (Sandbox Code Playgroud)

使用MVVM是另一种选择,它们也可以模板化东西,但实时修改可能需要手动触发重新渲染

  • 角度(打字稿,需要编译)
  • 反应(jsx,需要编译)
  • 角度 1.x
  • 视图