【问题标题】:How to Proxy Custom Element (Web Component)如何代理自定义元素(Web 组件)
【发布时间】:2017-04-08 20:38:36
【问题描述】:

class A extends HTMLElement {
  constructor() {
    super()
    return new Proxy(this, {})
  }
}

window.customElements.define('a-element', A)
<a-element></a-element>

如何代理自定义元素?

当我尝试时:

Uncaught InvalidStateError: custom element constructors must call super() first and must not return a different object.

【问题讨论】:

    标签: javascript web-component custom-element es6-class es6-proxy


    【解决方案1】:

    您可以代理自定义元素的实例

    鉴于以下自定义元素定义:

    class A extends HTMLElement {
      constructor() {
        super()
      }
      connectedCallback() {
        this.innerHTML = 'Hello'    
      }
    }
    customElements.define( 'a-element', A )
    

    自定义元素实例的代理

    从实例引用创建代理(此处:ae):

    <a-element id="ae"></a-element>
    <script>
      var b1 = new Proxy( ae, {
        get ( target, value ) { return target[value] }       
      } )
      console.log( b1.innerHTML ) // => "Hello"
    </script>
    

    自定义元素类的代理

    定义construct 陷阱以捕获new 运算符:

    <script>
      var B = new Proxy( A, {
        construct() { return new A }
      } )
      var b2 = new B
      document.body.appendChild( b2 )
      console.log( b2.innerHTML ) // => "Hello"
    </script>
    

    从类代理中获取自定义元素实例代理

    如果您想实例化一个自定义元素并直接获取一个代理对象,您可以结合上述两种解决方案。

    以下示例显示如何获取元素&lt;a-element&gt; 的代理,该代理将在控制台中记录每个属性访问。类 Proxy 中定义的 construct() 陷阱为实例化的自定义元素返回自己的代理。

    class A extends HTMLElement {
      constructor() {
        super()
      }
      connectedCallback() {
        this.innerHTML = 'Hello'    
      }
    }
    customElements.define( 'a-element', A )		
    
    var P = new Proxy( A, {
      construct () { 
        return new Proxy ( new A, {
          get ( target, value ) { 
            if ( value == 'element' ) 
              return target
            console.info( `proxy: property ${value} for <${target.localName}> is "${target[value]}"` )
            return target[value]
          }       
        } )
      }
    } )
    var p = new P
    document.body.appendChild( p.element )
    console.log( p.innerHTML )

    【讨论】:

    • 我需要将代理的逻辑封装在超类中。点赞:function P (_class) { return new Proxy (new class extends _class {}, {}) } class A extends P(HTMLElement) {} customElements.define( 'a-element', A ) 不过也不行
    • @АртурЛаврищев 改用function P (_class) { return new Proxy (class extends _class {}, {}) }(在class 之前没有new
    • @АртурЛаврищев 感谢您接受的答案,如果有帮助,您可以投票 :-)
    • 非常感谢您的回答。它在我的脑海中打开了一个灯泡——我几个月来一直在努力解决很多代码问题,这些技术可能会优雅地解决......
    • @diopside 只是好奇,您希望使用这些代理技术解决哪些代码问题?
    猜你喜欢
    • 2022-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    相关资源
    最近更新 更多