有没有办法阻止shadow dom内的javascript访问其外部的DOM?

问题描述 投票:0回答:2

所以如果我有:

js可以改变里面的文字

component_test_div

我可以阻止这种情况吗?

javascript dom shadow-dom
2个回答
3
投票

您可以对要保护的元素使用封闭的 Shadow DOM

component_test_div.attachShadow( { mode: "closed" } )
                  .innerHTML = "READ-ONLY"
                  
app_list.attachShadow( { mode: "closed" } )
        .appendChild( script.content )
<div id="component_test_div"></div>

<div id="app_list"></div>

<template id="script">
    <script>
        console.info( "shadowRoot is", component_test_div.shadowRoot )
        component_test_div.textContent = "SHADOWED BY SHADOW DOM"
    </script>
</template>

影子根的内容将替换任何初始或更改的文本。 close 属性将阻止其他脚本访问影子根目录。


2
投票

脚本不受 Shadow DOM 保护

Shadow DOM 仅保护 CSS 泄漏或对 ShadowRoot 内容的干扰。它不会为 JavaScript 创建新的命名空间。

在这段代码中,我在影子根中有一些JS:

class MyEl extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode:'open'});
    let s = document.createElement('script');
    s.textContent = "function dog() { console.log('Bark, Bark'); }";
    this.shadowRoot.appendChild(s);
  }
}

customElements.define('my-el', MyEl);

setTimeout(()=>dog(), 2000);
<my-el></my-el>

2 秒后,我们调用函数

dog()
并且它起作用了。这是因为,即使这段代码被放置到shadowRoot中,它仍然在全局范围内执行。

鉴于无法将 JavaScript 隔离在 Web 组件中,您需要记住它可供其范围内的任何人使用。

如果将代码放在 IIFE 中,则可以阻止外部调用。但是仍然无法阻止内部调用或操作范围之外的事物。


确定元素是否在 ShadowDOM 中的另一种方法

作为 @Angel Politis 答案的替代方法,有一种更简单的方法可以确定某个元素是否在某人的 ShadowRoot 中:

function isInShadowDOM(el) {
  let ret = false;

  if (el.getRootNode) {
    doc = el.getRootNode();
    ret = (doc !== document);
  }

  return ret;
}

© www.soinside.com 2019 - 2024. All rights reserved.