初识shadow dom

我们先看个input="range"的表现:

what amazing ! 一个dom能表现出这么多样式嘛?

无论是初学者和老鸟都是不肯相信的,于是在好奇心的驱使下,我们打开chrome的开发工具设置

结果发现了input节点里面有我们需要的答案

input节点里面有他表现需要的dom节点,dom节点里面还有些样式,而这些不容易为人知的节点都在一个#shadow-root的节点下面。

来张图了解下结构

document

这个很好理解,就是我们的正常文档 document 。

shadow host

对于一个内部有 shadow-dom 的元素而言,它必然需要一个宿主元素,对于上面的例子而言, <input> 标签,就是 shadow-dom 的宿主元素。

shadow-root

通过 createShadowRoot(下文会提及) 返回的文档片段被称为 shadow-root 。它和它的后代元素,都将对用户隐藏,但是它们是实际存在的,在 chrome 中,我们可以通常审查元素去查看它们的具体 DOM 实现。

在 此例子的 input 中,例如滑块,滑块条等都是 shadow-root 的后代。它们工作时会显示在屏幕上,但他们的 DOM 结构对用户是不可见的。

contents

就是上述所说的 input 中各子组件的 DOM 的具体实现。

shadow dom的api

下文先从例子出发学习api,再由API了解shadow dom的特性,不失为学习的好方法

helloWord:

 <div class="widget"></div>
<script>
var host = document.querySelector('.widget');
var root = host.createShadowRoot();
root.textContent = 'hello world!';
</script>

页面的效果是

dom结构也和想象中一样:在div.widget>shadow-root>text(hello world)

shadowHost.createShadowRoot:在shadowHost内创建ShadowRoot节点
dom操作
再来个简单的例子
<body>
<div class="widget">Hello, world!</div>3 <script>
var host = document.querySelector('.widget');
var root = host.createShadowRoot(); var header = document.createElement('h1');
header.textContent = '影子标题'; var paragraph = document.createElement('p');
paragraph.textContent = '影子文本'; root.appendChild(header);
root.appendChild(paragraph);
</script>
</body>

效果和dom结构也和想象中一样,只是div.widget(shadowHost)内的内容不见了,没错,在有shadowDom的情况下ShadowHost内的真实节点并不会渲染。

从这个例子发现普通的dom操作在shadowDom也是可行的

template/content

在之前的例子里,我们用shadow root里面的内容完全替换掉了shdow host里面的内容。但这种奇技淫巧在实际开发中没什么用。真正有用的是我们可以从shdow host中获取内容,并使用shdow root中的结构将这些内容呈现

<body>
<div class="widget">
ShadowRootText
</div> <template class="template">
<h1>ShadowRoot的内容出现了 <content>ShadowRootText</content> 出现了!</h1>
</template> <script>
var host = document.querySelector('.widget');
var root = host.createShadowRoot();
var template = document.querySelector('.template');
root.appendChild(document.importNode(template.content, true));
</script>
</body>

效果如下

dom结构也是想象中的那样:shadow host里面的内容都插进了shadow root的content节点里面了

使用 <content> 标签,我们创建了一个insertion point(<content>),其将 div.pokemon 中的文本projects 出来,使之得以在我们的影子节点 <h1> 中展示。

插入点十分强大,它允许我们在不改变源代码的情况下改变渲染顺序,这也意味着我们可以对要呈现的内容进行选择。

select 属性

<body>
<div class="widget">
<span class="contury">中国</span>
<span class="city">广州</span>
<span class="province">广东</span>
<p>广州好很塞车</p>
</div> <template class="template">
<dl>
<dt>国家</dt>
<dd><content select=".contury"></content></dd>
<dt>省份</dt>
<dd><content select=".province"></content></dd>
<dt>城市</dt>
<dd><content select=".city"></content></dd>
</dl>
<p><content select=""></content></p>
</template> <script>
var host = document.querySelector('.widget');
var root = host.createShadowRoot();
var template = document.querySelector('.template');
root.appendChild(template.content);
</script>
</body>

页面效果

dom结构

在这个例子中,content里面能选择shadow root里面的insertion point能通过select属性选择出shadow host里面的内容,

并且,页面显示顺序是按照shadow root里面的template顺序显示,并不会按照shadow host的数据显示顺序显示,由此可发现

shadow root 负责渲染的结构、顺序,shadow host负责渲染的数据(接触过angularJS的directive的你是否看完后是否会微微一笑)

贪心插入点

<body>
<div class="widget">
<p>shadow host text</p>
</div> <template class="template"> <p><content ></content>
<p><content select=""></content>
<p><content select="*"></content> </template> <script>
var host = document.querySelector('.widget');
var root = host.createShadowRoot();
var template = document.querySelector('.template');
root.appendChild(template.content);
</script>
</body>

template有三个content,三个content都是匹配shadow host的内容的,那么显示的效果是三行文本还是一行呢?

结果显示是这样的

dom结构是这样的

这是因为这个选择器是贪心的,而且元素只能被选择一次。我们一旦把贪心选择器匹配了shadow host的内容,他就会将所有内容都抓取,不给其他 select 选择器留一点内容。

样式封装

shadow DOM 有着独立的样式作用域(shadow boundary),shadow boundary的主要好处就是防止主 DOM 中的样式泄露到 shadow DOM 中。

这就意味着即使你在主文档中有一个针对全部标签的样式选择器,这个样式也不会不经你的允许便影响到 shadow DOM 的元素。

来个例子:

<body>
<style>
p {
font:18/1.5 SimSum;
}
</style>
<p>this is normal text</p>
<div></div> <script>
var host = document.querySelector('div');
var root = host.createShadowRoot();
root.innerHTML = '<style>p { font:bold 30px/60px "microsoft yahei";color:red } </style>' +
'<p>this is shadow text</p>'
</script>
</body>

显示的效果是这样的

normal text的样式并不会对shadow text产生影响,一个困扰前端届多年的独立CSS作用域就这么实现了。

Amazing,不用担心改这个按钮的样式也会影响到其他页面的按钮了,赞~

宿主样式(:host)

我经常把shadow host想象成一栋建筑物的外表。这栋建筑物的内部有组件的全部运行方式,外面有一个好的门面。 许多情况下你可能会想给这门面调整一下样式,这就轮到 :host 选择器出场了。

<body>
<style>
.widget {
text-align: center;
}
</style> <div class="widget">
<p>Hello World!</p>
</div> <script>
var host = document.querySelector('.widget');
var root = host.createShadowRoot();
root.innerHTML = '<style>' +
':host {' +
' border: 2px dashed red;' +
' text-align: left;' +
' font-size: 28px;' +
'} ' +
'</style>' +
'<content></content>';
</script>
</body>

显示的效果是下图

文字28px,还有个小边框,文字是居中对齐的,并没有按照shadow root里面



shadow dom的更多相关文章

  1. 【shadow dom入UI】web components思想如何应用于实际项目

    回顾 经过昨天的优化处理([前端优化之拆分CSS]前端三剑客的分分合合),我们在UI一块做了几个关键动作: ① CSS入UI ② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀 ...

  2. 封印术:shadow dom

    置顶文章:<纯CSS打造银色MacBook Air(完整版)> 上一篇:<鼠标滚动插件smoovejs和wowjs> 作者主页:myvin 博主QQ:851399101(点击Q ...

  3. 使用shadow dom封装web组件

    什么是shadow dom? 首先我们先来看看它长什么样子.在HTML5中,我们只用写如下简单的两行代码,就可以通过 <video> 标签来创建一个浏览器自带的视频播放器控件. <v ...

  4. shadow dom 隔离代码 封装

    Shadow DOM是指浏览器的一种能力,它允许在文档(document)渲染时插入一棵DOM元素子树,但是这棵子树不在主DOM树中.   Shadow DOM 解决了 DOM 树的封装问题.     ...

  5. 纯CSS菜单样式,及其Shadow DOM,Json接口 实现

    先声明,要看懂这篇博客要求你具备少量基础CSS知识, 当然如果你只是要用的话就随便了,不用了解任何知识 完整项目github链接:https://github.com/git-Code-Shelf/M ...

  6. JavaScript 是如何工作:Shadow DOM 的内部结构 + 如何编写独立的组件!

    这是专门探索 JavaScript 及其所构建的组件的系列文章的第 17 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...

  7. Shadow DOM及自定义标签

    参考链接:点我 一.什么是Shadow DOM Shadow DOM,直接翻译的话就是 影子 DOM,可以理解为潜藏在 DOM 结构中并且我们无法直接控制操纵的 DOM 结构.类似于下面这种结构 Sh ...

  8. 理解Shadow DOM(一)

    1. 什么是Shadow DOM? Shadow DOM 如果按照英文翻译的话可以理解为 影子DOM, 何为影子DOM呢?可以理解为一般情况下使用肉眼看不到的DOM结构,那如果一般情况下看不到的话,那 ...

  9. html 中shadow DOM 的使用

    什么是shadow DOM? An important aspect of web components is encapsulation — being able to keep the marku ...

随机推荐

  1. codeblocks快捷键及设置

    ==日常编辑== • 按住Ctrl滚滚轮,代码的字体会随你心意变大变小.• 在编辑区按住右键可拖动代码,省去拉(尤其是横向)滚动条之麻烦:相关设置:Mouse Drag Scrolling.• Ctr ...

  2. 质因数分解的rho以及miller-rabin

    一.前言 质因数分解,是一个在算法竞赛里老生常谈的经典问题.我们在解决许多问题的时候需要用到质因数分解来辅助运算,而且质因数分解牵扯到许许多多经典高效的算法,例如miller-rabin判断素数算法, ...

  3. Tour(KM算法)

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submi ...

  4. STL 源代码剖析 算法 stl_algo.h -- partition

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie partition ------------------------------------ ...

  5. [POJ 1521]--Entropy(哈夫曼树)

    题目链接:http://poj.org/problem?id=1521 Entropy Time Limit: 1000MS    Memory Limit: 10000K Description A ...

  6. [转][Swust OJ 24]--Max Area(画图分析)

    转载自:http://www.cnblogs.com/hate13/p/4160751.html Max Area 题目描述:(链接:http://acm.swust.edu.cn/problem/2 ...

  7. ZOJ 3872 Beauty of Array DP 15年浙江省赛D题

    也是一道比赛时候没有写出来的题目,队友想到了解法不过最后匆匆忙忙没有 A 掉 What a pity... 题意:定义Beauty数是一个序列里所有不相同的数的和,求一个序列所有字序列的Beauty和 ...

  8. 利用SolrJ操作solr API完成index操作

    使用SolrJ操作Solr会比利用httpClient来操作Solr要简单.SolrJ是封装了httpClient方法,来操作solr的API的.SolrJ底层还是通过使用httpClient中的方法 ...

  9. 编译原理Tiny语言的定义

    Here is the definition for Tiny language The Tiny lexicon is as follows: Keywords:   IF ELSE WRITE R ...

  10. JAVAC 命令使用方法

    结构 javac [ options ] [ sourcefiles ] [ @files ] 參数可按随意次序排列. options 命令行选项. sourcefiles 一个或多个要编译的源文件( ...