【问题标题】:How do I bind a function to elements inside of a Shadow DOM?如何将函数绑定到 Shadow DOM 内的元素?
【发布时间】:2015-02-05 23:48:50
【问题描述】:

我正在使用 Web 组件并尝试将 click 事件绑定到 Shadow DOM 内的元素。

1. component.html 包含在 index.html 中的<link rel="import" ...>

<template id="my-element">
    <section>
        <header>
            <content select="h1"></content>
            <button></button>
        </header>
        <content select="div"></content>
    </section>
</template>

2。后期元素使用:

<my-element>
    <h1>Headline</h1>
    <div>...</div>
</my-element>

3.访问元素并将函数绑定到它

现在我想添加一个addEventListener() 到我的&lt;button&gt; 内的&lt;my-element&gt; (不幸的是通过#shadow-root 隐藏)。喜欢:

var elemBtn = document.querySelector('my-element button');
elemBtn.addEventListener('click', function(event) {
    // do stuff
});

但这行不通。 我如何做到这一点?

【问题讨论】:

    标签: javascript html web-component shadow-dom custom-events


    【解决方案1】:

    您应该能够在不涉及窗口对象的情况下执行此操作。这是一个完整的例子:

    <!-- Define element template -->
    <template>
      <h1>Hello World</h1>
      <button id="btn">Click me</button>
    </template>
    
    <!-- Create custom element definition -->
    <script>
      var tmpl = document.querySelector('template');
    
      var WidgetProto = Object.create(HTMLElement.prototype);
    
      WidgetProto.createdCallback = function() {
        var root = this.createShadowRoot();
        root.appendChild(document.importNode(tmpl.content, true));
        // Grab a reference to the button in the shadow root
        var btn = root.querySelector('#btn');
        // Handle the button's click event
        btn.addEventListener('click', this.fireBtn.bind(this));
      };
    
      // Dispatch a custom event when the button is clicked
      WidgetProto.fireBtn = function() {
        this.dispatchEvent(new Event('btn-clicked'));
      };
    
      var Widget = document.registerElement('my-widget', {
        prototype: WidgetProto
      });
    </script>
    
    <!-- Use the element -->
    <my-widget></my-widget>
    
    <!-- Listen for its click event -->
    <script>
      var widget = document.querySelector('my-widget');
      widget.addEventListener('btn-clicked', function() {
        alert('the button was clicked');
      });
    </script>
    

    Example on jsbin

    【讨论】:

    • 这很令人沮丧。你的解决方案比我的聪明得多:D
    • @morkro 您介意将此答案标记为正确吗?
    • 当然!感谢@robdodson 向我展示了一个更好的方法:)
    【解决方案2】:

    我发现在&lt;template&gt; 内部创建一个自定义createEvent('MouseEvent'); 可以解决问题!

    TL;DR http://jsfiddle.net/morkro/z0vbh11v/


    1.首先,您需要将onclick=""-attribute 添加到我们的&lt;template&gt; 并创建一个自定义事件:

    <template id="my-element">
        <section>
            <header>
                <content select="h1"></content>
                <button onclick="callEventOnBtn()"></button>
            </header>
            <content select="div"></content>
        </section>
    
        <script>
            var btnEvent = document.createEvent('MouseEvent');
            btnEvent.initEvent('oncomponentbtn', true, true);
            var callEventOnBtn = function() {
                window.dispatchEvent(btnEvent);
            };
        </script>
    </template>
    

    我在 &lt;template&gt; 内创建自定义事件,并在以后使用自定义元素时自动将其分派给全局 window 对象。

    2。现在我们可以在点击自定义元素上的&lt;button&gt; 时监听该事件

    window.addEventListener('oncomponentbtn', function(event) {
        // do stuff
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-06
      • 2020-11-25
      • 2020-05-09
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多