将元素后期“手动”升级为定制的内置Web组件

时间:2018-07-24 09:46:06

标签: javascript html5 ecmascript-6 web-component native-web-component

我有一个动态创建div的jQuery插件(我不想修改)。除此之外,我还有一个Web组件scrollable-div,它是一个自HTMLDivElement扩展而成的自定义内置组件。由于我无法控制jQuery插件如何创建div,因此我需要在创建后以及将其添加到DOM后对其进行升级。

class myDiv extends HTMLDivElement {
  constructor(...args) {
    const self = super(...args);
    self.addEventListener('click', (e) => {
      e.target.textContent = 'clicked'
    })
    return self;
  }
}

customElements.define('my-div', myDiv, { extends: 'div' });

document.addEventListener('DOMContentLoaded', () => { 
  // this is where I'm trying to turn the div#upgradeMe into a my-div
  upgradeMe.setAttribute('is', 'my-div');
});
<div id="upgradeMe">Click me</div>

仅添加is="my-div"属性显然不能解决问题,div只是保持常规HTMLDivElement。如何以编程方式将DOM中已经存在的本机元素升级为自定义的内置Web组件?

2 个答案:

答案 0 :(得分:1)

这是不可能的,因为由于缺少<div>属性,该元素已经被创建为标准is元素,并且在解析为 upgradeable (可扩展)时没有被标识

如果已经定义了自定义元素,则唯一可行的解​​决方法是用克隆替换现有元素(如@barbsan的注释中所建议)。

简而言之:

  1. 创建一个<template>元素
  2. 将div的outerHTML复制到其innerHTML属性中
  3. 用模板模板的contentreplaceChild()替换原始元素

class myDiv extends HTMLDivElement {
  constructor(...args) {
    const self = super(...args);
    self.addEventListener('click', (e) => {
      e.target.textContent = 'clicked'
    })
    return self;
  }
}

customElements.define('my-div', myDiv, { extends: 'div' });

document.addEventListener('DOMContentLoaded', () => { 
  // this is where I'm trying to turn the div#upgradeMe into a my-div
  upgradeMe.setAttribute('is', 'my-div');
  var t = document.createElement( 'template' )
  t.innerHTML = upgradeMe.outerHTML
  upgradeMe.parentElement.replaceChild( t.content, upgradeMe )
});
<div id="upgradeMe">Click me</div>

规定

解析元素时,是值受到影响according to the DOM spec

  

元素具有关联的名称空间,名称空间前缀,本地名称,自定义元素状态,自定义元素定义,是值。创建元素时,所有这些值都将初始化。

只有具有有效is属性的元素才被标识为可自定义:

  

元素的自定义元素状态是“未定义”,“失败”,“未自定义”或“自定义”之一。据说定义了其自定义元素状态为“未自定义”或“自定义”的元素。定制元素状态为“ custom”的元素被称为定制元素。

因此,如果元素在解析时没有is属性,则将无法自定义。这就是为什么您以后不能添加is属性的原因。

也在HTML specs中:

  

创建自定义元素后,更改 is 属性的值不会更改元素的行为,因为它以 is值保存在元素上。

is属性仅在元素创建时(在解析时)用于初始化 is值,并且在已创建元素时更改后无效。从这个意义上说,是只读的。

答案 1 :(得分:0)

如果要支持所有现代浏览器,则无法自定义内置组件,Apple表示它们将永远不支持is =“” https://github.com/w3c/webcomponents/issues/509#issuecomment-222860736