在Shadow DOM(二)中,介绍了与Shadow DOM相关的概念,包括Shadow host等等。
本文将重点介绍如何将Light DOM中的内容传到Shadow DOM中。
而在Shadow DOM 与HTML Templates一文的示例中可以看到Shadow host: <div class="host">Hello World!</div>的内容在该节点创建并附加Shadow Root后并没有在浏览器中得到渲染,也就是说Shadow host的内容,这里为“Hello
World!"没能在浏览器中渲染出来,取而代之的是Shadow DOM中的内容得到了渲染,及该例中的template中的内容得到了渲染,然后在浏览器中运行后,只看到了Shadow DOM中的内容。
然后,在实际应用中,这种完全用Shadow DOM替换Light DOM中内容的方式并不是很有用,我们期望实现的可以通过从Shadow host中获取内容,然后使用Shadow DOM提供的结构来展现。类似这样的内容与展现分离,可以让我们在处理页面如何渲染的过程中更加灵活。
为了能够使用我们在Shadow host的内容,我们需要引入一个新的标签,那就是<content>标签。
首先通过一个示例来了解:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Demo</title> </head> <body> <div class="host">Hello Wrold!</div> <template> <h2>Hi, my name is winstar, and I can say: <content></content></h2> </template> <script> var host = document.querySelector('.host'); var root = host.createShadowRoot(); var tmpl = document.querySelector('template'); root.appendChild(document.importNode(tmpl.content, true)); </script> </body> </html>
在Chrome浏览器中运行,效果如图:
可以看到,在源代码中的template,包含了<content>标签,而在运行结果中,也可以看到Shadow host中的内容“Hello World!"也被渲染了出来,而且就是<content>标签所在的位置。
通过<content>标签,我们在模板中创建了一个插入点,这个插入点可以投射来自Shadow host中的内容,如本例中的“Hello World!”投射到<content>所在位置,并出现在我们的h2标签中。
插入点的功能非常强大,它允许我们在不手动修改源代码(这里的源代码指的是Shadow host中出现的内容)的基础上也可以改变渲染的顺序,也让开发者可以有选择性地选取哪些内容应该得到渲染。
刚刚说到,插入点可以改变渲染的顺序,有选择性地选取哪些内容应该得到渲染,这个是如何实现的呢?为了实现这一目的,必须让<content>具备选择能力,让它知道选择哪里的内容插入到指定的位置。为了做到这一点,规范赋予了<content>标签具有select属性。这个select属性使用CSS选择器来匹配选择需要渲染的内容。
例如,<content select=".user-name">将在Shadow host中查找任何具有class为user-name的匹配元素,并将所有匹配元素插入到该<content>标签中以被渲染。
改变顺序示例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Demo</title> </head> <body> <div class="host"> <div class="name">winstar</div> <div class="age">28</div> </div> <template> <h2><content select=".name"></content></h2> <h2><content select=".age"></content></h2> </template> <script> var host = document.querySelector('.host'); var root = host.createShadowRoot(); var tmpl = document.querySelector('template'); root.appendChild(document.importNode(tmpl.content, true)); </script> </body> </html>
运行结果:
在该示例中,可以看到<content>通过select属性分别选取了Shadow host中对应的内容,并且得以被渲染出来。下面我们在不需改内容结构的情况下,调整渲染的顺序。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Demo</title> </head> <body> <div class="host"> <div class="name">winstar</div> <div class="age">28</div> </div> <template> <h2><content select=".age"></content></h2> <h2><content select=".name"></content></h2> </template> <script> var host = document.querySelector('.host'); var root = host.createShadowRoot(); var tmpl = document.querySelector('template'); root.appendChild(document.importNode(tmpl.content, true)); </script> </body> </html>
运行结果:
可以看到,浏览器渲染内容的顺序跟前面确实改变了,但通过【审查元素】可以发现Shadow host的内容(红框中的内容)属性却保持跟原来一模一样。
因此,可以说内容是在Shadow host中的,而决定渲染的是Shadow root/Shadow DOM。