什么是shadow DOM?
将一组隐藏的、独立的DOM结构附加到某个元素上。比如在video元素的shadow DOM上,就隐藏了许多对视频控制的按钮和控制器等。
shadow host:一个常规的DOM节点,shadow DOM 会被附加到这个节点上
shadow tree:shadow DOM 内部的DOM tree
shadow root:shadow tree的根节点
shadow boundary:shadow tree结束的地方,也就是常规DOM开始的地方
和操作常规DOM一样,可以用相同的方式操作Shadow DOM ,比如为其添加子节点,设置属性、样式等。不同的是,shadow DOM 始终不会影响其外部的元素,
除了:focus-within(是一个css伪类,表示一个元素获得焦点,或该元素的后代获得焦点)
基本用法
Element.attachShadow()
:
将一个shadow root添加到某个元素上,接收一个对象作为参数:{mode: 'open/closed'}。当为open时允许以js的方式操作shadow DOM,closed时不允许外部对其进行操作
如果想将一个shadow DOM 附加到常规DOM上,就可以在常规DOM的构造函数中:
let shadow = this.attachShadow({mode: 'open'});
之后就可以通过js对其进行操作,如下
let img = document.createElement('img'); shadow.appendChild(img);
以下为MDN中的示例:shadow dom包含一个图片icon和一个隐藏的info,当图片icon获得焦点时info显示,内容为说明信息
<html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body>
<!--在页面中直接使用 --> <popup-info img="C:\Users\asus\Pictures\Saved Pictures" text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."> </body> <script>
// 创建一个常规DOM,用来添加shadow dom class popUpInfo extends HTMLElement{ constructor(){ super();
// 创建一个shadow root var shadow = this.attachShadow({mode: 'open'});
// 创建三个span。并未它们赋予class属性和值 var wrapper = document.createElement('span'); wrapper.setAttribute('class', 'wrapper'); var icon = document.createElement('span'); icon.setAttribute('class', 'icon'); icon.setAttribute('tabindex', 0); var info = document.createElement('span'); info.setAttribute('class', 'info');
// 将当前元素上的text属性值赋值给info的内容,info就是用来显示图片的说明信息 var text = this.getAttribute('text'); info.textContent = text;
// 将当前元素的img属性值获取,创建一个img元素,放到icon中 var imgUrl; if (this.hasAttribute('img')) { imgUrl = this.getAttribute('img'); }else{ imgUrl = 'img/default.png'; } var img = document.createElement('img'); img.src = imgUrl; icon.appendChild(img);
// 为 shadow DOM 添加一些 CSS 样式 var style = document.createElement('style'); style.textContent = `.wrapper { position: relative; } .info { font-size: 0.8rem; width: 200px; display: inline-block; border: 1px solid black; padding: 10px; background: white; border-radius: 10px; opacity: 0; transition: 0.6s all; position: absolute; bottom: 20px; left: 10px; z-index: 3; } img { width: 1.2rem; } .icon:hover + .info, .icon:focus + .info { opacity: 1; }`;
// 将样式和wrapper添加给shadow shadow.appendChild(style); shadow.appendChild(wrapper);
// wrapper中包含icon和info wrapper.appendChild(icon); wrapper.appendChild(info); } } // 定义常规DOM customElements.define('popup-info', popUpInfo); </script> </html>