1

我正在使用自定义元素,我注意到在一种情况下我无法访问实例的属性,就像在var prop = myCustomElement.myPropery // undefined类中将属性定义为 eg 一样get myProperty() { blah }

myCustomElement.constructor当自定义元素在脚本 type="module" 中定义与没有模块类型时,我将问题归结为报告的内容(以及原型/实例类型)。

这是一个非常简单的例子:

var test = document.getElementById ( "test" );

console.log ( test.mood, test.constructor );
<script type="module">
const template = document.createElement ( "template" );

template.innerHTML = "<span>Hello!</span>";

window.customElements.define ( "test-case",

class TestCase extends window.HTMLElement {
    constructor () {
        super ();
        
        var frag = template.content.cloneNode ( true ),
            shadow = this.attachShadow( { mode: "open" } );
        
        shadow.appendChild ( frag );
    }
    
    get mood () {
        return "Happy!";
    }
} );
</script>
<test-case id="test"></test-case>

...并且没有模块类型

var test = document.getElementById ( "test" );

console.log ( test.mood, test.constructor );
<script>
const template = document.createElement ( "template" );

template.innerHTML = "<span>Hello!</span>";

window.customElements.define ( "test-case",

class TestCase extends window.HTMLElement {
    constructor () {
        super ();
        
        var frag = template.content.cloneNode ( true ),
            shadow = this.attachShadow( { mode: "open" } );
        
        shadow.appendChild ( frag );
    }
    
    get mood () {
        return "Happy!";
    }
} );
</script>
<test-case id="test"></test-case>

这似乎很错误,这种行为是故意的吗?

而且,假设需要使用模块来定义要在更大组件或库中使用的自定义元素,是否有直接的方法来防止模块隐藏自定义元素的类型?

注意:我正在从最新的 Chrome (74.0.3729.157) 测试这个,还没有尝试过其他浏览器。

4

2 回答 2

1

您的非模块脚本在模块脚本之前运行。所以你只需要等到元素被定义但调用customElements.whenDefinedhttps ://devdocs.io/dom/customelementregistry/whendefined

window使用customElementsor时也没有理由使用HTMLElement

customElements.whenDefined('test-case').then(
  () => {
    const test = document.getElementById ( "test" );
    console.log ( test.mood, test.constructor );
  }
);
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
customElements.define ( "test-case",
  class TestCase extends HTMLElement {
    constructor () {
      super ();
      const frag = template.content.cloneNode ( true );
      const shadow = this.attachShadow( { mode: "open" } );
      shadow.appendChild ( frag );
    }
    
    get mood () {
      return "Happy!";
    }
  }
);
</script>
<test-case id="test"></test-case>

于 2019-05-29T14:19:41.760 回答
1

您需要等到元素被定义。

自定义元素注册表。when定义()

CustomElementRegistry 接口的whenDefined()方法返回一个 Promise,该 Promise 在定义命名元素时解析。

customElements.whenDefined('test-case').then(
  () => {
    const test = document.getElementById("test");
    console.log(test.mood, test.constructor);
  }
);
<script type="module">
const template = document.createElement ( "template" );

template.innerHTML = "<span>Hello!</span>";

window.customElements.define ( "test-case",

class TestCase extends window.HTMLElement {
    constructor () {
        super ();
        
        var frag = template.content.cloneNode ( true ),
            shadow = this.attachShadow( { mode: "open" } );
        
        shadow.appendChild ( frag );
    }
    
    get mood () {
        return "Happy!";
    }
} );
</script>
<test-case id="test"></test-case>

于 2019-05-20T10:36:38.870 回答