shadowRoot是由元素的Element.attachShadow()创建的并使 mode设置为 open。如以下事例代码
window.onload = () => { const app = document.getElementById(app) // 在元素上添加shadowRoot的方法,生成shadow实例 const shadow = app.attachShadow({ mode: open }) // 创建htmlElement并在其内部写入一个id为title的h1标签 const div = document.createElement(div) div.innerHTML= `<h1 id="title">hello world</h1>` // 创建style标签 const style = document.createElement(style) // 把htmlElement元素挂载到shadow实例对象上 shadow.appendChild(style) shadow.appendChild(div) // 写入style的样式 shadow.querySelector(style).textContent = ` div { width: 250px; height: 100px; background-color: pink; display: flex; justify-content: center; } ` // 选择shadowRoot内部的DOM元素 const title = shadow.querySelector(#title) console.log(title) // shadow.mode是只读属性,无法修改 shadow.mode = close //无效 console.log(shadow.mode) // open } 控制台打印效果页面元素结构目前主流浏览器已经支持了shadowRoot的使用
说到楼主的问题,当shadow.mode = close的情况。也就是说无法修改,无法获取,甚至你创建后都无法挂载元素在其之上。这定义了 shadow root 的内部实现是否可被 JavaScript 访问及修改 — 也就是说,该实现是否公开。
‘close’属性通常是如video、textaera、input标签的默认的行为,为保证访问的安全。
video、textaera、input标签的默认shadowRoot const video = document.getElementById(video) const videoShadow = video.shadowRoot // 尝试获取video内部的shadow Dom console.log(videoShadow)// null console.dir(video) // 内部未公开,使用video同样也能操作 控制台未能获取通常我们获取这些元素的内部并不会以获取shadow Dom的元素,而是直接获取Dom元素的方法,Dom元素是直接暴露给用户的,你可以很方便去自定义。
那shadow Dom是用来做什么的?
Shadow DOM 被设计为用于构建基于组件的应用程序的工具。因此,它带来了Web开发中常见问题的解决方案:
隔离 DOM:组件的 DOM 是自包含的(例如, document.querySelector()不会返回组件shadow DOM 中的节点)。作用域 CSS:在 shadow DOM 中定义的 CSS 是作用域的。样式规则不会泄露,页面样式也不会渗入。组合:为您的组件设计一个声明性的、基于标记的 API。简化 CSS - Scoped DOM 意味着您可以使用简单的 CSS 选择器、更通用的 id/class 名称,而不必担心命名冲突。生产力- 以 DOM 块而不是全局页面来考虑。简单的说你可以使用它来模块化你的组件,自定义组件,让用户不用关心内部的实现,而是去使用它。
在某些情况下,可以通过"劫持"Element.prototype.attachShadow,来访问shadow-root中的closed节点。
Element.prototype._attachShadow = Element.prototype.attachShadow; Element.prototype.attachShadow = function () { return this._attachShadow({mode:open}); };