外部脚本是否可以绑定一个事件监听器到 Shadow DOM 中的元素?

16

我有一个Chrome扩展程序,它会将一个影子DOM元素注入到页面中,以保持CSS的独立性。但是,我需要在内容脚本中为影子DOM中的某些元素绑定onclick事件,因为我需要能够通过单击位于影子DOM中的元素来调用内容脚本中的函数。

我尝试在模板元素和实际影子DOM元素上都使用.bind('click', function(){}),但是似乎无法访问它们。这种情况可能吗?

3个回答

25

尝试查询元素的 shadowRoot。换句话说,假设您有一个元素 <super-ultra-element>,并且在该元素的 shadow dom 内部有一个带有类别“potato”的 div,您希望将点击处理程序附加到它上面。

首先通过获取元素的 shadowRoot 来实现此目标:var superUltraRoot = document.querySelector('super-ultra-element').shadowRoot;

一旦您获得了 shadowRoot,就可以查询您关心的元素的 shadow dom:var potatoDiv = superUltraRoot.querySelector('.potato');

现在,您已经有了对您想要添加点击处理程序的元素的引用,所以这样做应该相当容易:potatoDiv.addEventListener('click', someClickCallback);


2
虽然我不得不使用querySelectorAll,但这绝对是正确的答案。 - Shawn Volpe

0

我已经尝试在模板元素中使用.bind('click', function(){}),

  1. 向模板添加事件监听器是行不通的。您绑定的元素应该是DOM的一部分。

但我似乎无法访问它们,包括实际的影子DOM元素。

  1. 我认为jQuery还不理解影子根。如果您正在使用jQuery查询影子DOM中的元素,则不认为它会返回节点(应该吗?)

所以,您有两个选择:

  1. 如其他答案建议的那样,您可以通过在影子根内查询元素来将事件监听器绑定到实际元素上,这可以通过元素上的shadowRoot属性访问。
  2. 或者,您可以使用jQuery event-delegation 在父级(在本例中为host)上使用适当的选择器绑定事件侦听器。当事件传播到父级时,侦听器将被触发。

例如:

$( "#list" ).on( "click", "a", function( event ) {
    event.preventDefault();
    console.log( $( this ).text() );
});

0

我正在使用 Jquery 的替代方式 findon 函数,在这里尝试我的片段。

$("#CreateShadowRoot").on('click', function (event) {
    const shadowDiv = document.getElementById('ShadowDiv');
    const shadowRoot = shadowDiv.attachShadow({ mode: 'open' });
    const jQueryScript = document.createElement('script');
    jQueryScript.src = 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'; 
    shadowRoot.appendChild(jQueryScript);
    shadowRoot.innerHTML += '<button id="example-action">Im inside ShadowRoot</button>';
    function initShadowDOM() {
      // Get the Shadow DOM root element
      // Attach a click event listener using jQuery
      $(shadowRoot).find("#example-action").on('click', function (event) {
        // Handle the click event within the Shadow DOM
        // You can access the event object and perform actions here
        console.log('Event received');
      });
    }
    jQueryScript.onload = function () {
      // jQuery is now loaded and ready to use
      // You can use jQuery event listeners like .on() here
      initShadowDOM(); // Call a function to set up the Shadow DOM content and event listeners
    };
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="CreateShadowRoot">Create ShadowRoot</button>
<div id="ShadowDiv"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接