使用shadow dom封装web组件
什么是shadow dom?
首先我们先来看看它长什么样子。在HTML5中,我们只用写如下简单的两行代码,就可以通过 <video> 标签来创建一个浏览器自带的视频播放器控件。
<video controls="">
<source src="https://mdn.mozillademos.org/files/2587/AudioTest%20(1).ogg" type="audio/ogg">
</video>
而在各个浏览器中,它都有各不相同的外观展现,例如chrome中它长下面这样:
但为什么我们在dom中无法看到他们内部的结构?噢,实际上浏览器通过某种技术把它们隐藏起来而已,但我们可以通过 DevTools 设置中勾选Show user agent shadow DOM来看到这些结构。勾选后我们发现在 <video> 标签下多了 #shadow-root(user-agent) 这个东西,它包含了 video 控件的内部dom结构,这就是所谓的shadow dom了。
并且shadow dom为我们提供了简单有效的样式隔离。如果你尝试通过 input[type="button"] { display:none; } 之类的样式来影响控件外观,你会发现是无效的。这样如果我们通过 shadow dom 来隐藏控件的内部实现,就不用担心对样式表进行修改时对控件造成影响了。
下面我们来看看如何通过shadow dom来封装控件。
使用Shadow Dom封装控件
首先我们先看看w3c对shadow dom的描述:
A shadow host is an element that hosts one or more node trees.
A shadow tree is a node tree hosted by a shadow host.
A shadow root is the root node of a shadow tree.
这三句话告诉我们:
- - shadow dom 由一颗或多颗 shadow tree 组成,并且需要一个普通的dom元素作为它的容器
- - shadow tree 是一颗节点树
- - shadow root 是shadow tree的根节点
下面,我们直接通过一个例子来演示如何使用shadow dom来封装web组件:
DOM:
// 模板
<template id="wgTemplate">
<style>
color: #fff;
background: #006dcc;
</style>
<button type="button" class="btn">button widget</button>
</template> // shadow dom 容器
<div id="my-widget"></div>
JS:
// 创建shadow dom
<script type='text/javascript'>
var host = document.querySelector("#my-widget")
var tp = document.querySelector("#wgTemplate")
var clone = document.importNode(tp.content, true)
host.createShadowRoot().appendChild(clone)
</script>
- 第一步,我们需要一个shadow dom的容器 <div id="my-widget"></div>
- 随后通过 document.importNode() 获取到控件的模板并克隆
- 接着使用 createShadowRoot() 要创建一个shadow root作为shadow tree的根节点
- 最后将将模板内容 clone 作为shadow tree插入到shadow root中
打开页面,我们可以看到如下结构,这就是一个利用shadow隐藏控件内部实现最简单的例子了。
接着我们还可以结合上一篇文章《web component之custom element》的创建自定义元素的方法来封装自定义控件:
dom:
// 模板
<template id="wgTemplate">
<style>
.btn {
color: #fff;
background: #006dcc;
}
</style>
<button type="button" class="btn">custom button widget</button>
</template>
js:
// 创建自定义控件
<script type='text/javascript'>
var proto = Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var tp = document.querySelector('#wgTemplate')
var clone = document.importNode(tp.content, true)
this.createShadowRoot().appendChild(clone)
}
}
}) var MyButtom = document.registerElement('my-buttom', {prototype: proto}) document.body.appendChild(new MyButtom())
</script>
使用shadow dom封装web组件的更多相关文章
- 【shadow dom入UI】web components思想如何应用于实际项目
回顾 经过昨天的优化处理([前端优化之拆分CSS]前端三剑客的分分合合),我们在UI一块做了几个关键动作: ① CSS入UI ② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀 ...
- atitit. web组件化原理与设计
atitit. web组件化原理与设计 1. Web Components提供了一种组件化的推荐方式,具体来说,就是:1 2. 组件化的本质目的并不一定是要为了可复用,而是提升可维护性. 不具有复用 ...
- atitit.atiHtmlUi web组件化方案与规范v1
atitit.atiHtmlUi web组件化方案与规范v1 1. 如何在现有html 标签基础上定义自己的组件1 2. 组件的构成与定义1 3. 组件的加载1 4. 组件css的加载2 5. 操作组 ...
- 究竟什么是Shadow DOM?
shadow dom 是什么? 顾名思义,shadow dom直译的话就是影子dom,但我更愿把它理解为DOM中的DOM.因为他能够为Web组件中的 DOM和 CSS提供了封装,实际上是在浏览器渲染文 ...
- 从原生web组件到框架组件源码(三)
快乐的时光都是这么短暂,转眼间,web原生组件的知识点已经学完了,这个虽然暂时不一定有用,但是随着时间的积累,一步一个脚印的积累,你会有相应的收获,希望能变得更强,比如两年前我也会想有现成的东西不用, ...
- JavaScript 是如何工作:Shadow DOM 的内部结构 + 如何编写独立的组件!
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 17 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...
- 【Web技术】401- 在 React 中使用 Shadow DOM
本文作者:houfeng 1. Shadow DOM 是什么 Shadow DOM 是什么?我们先来打开 Chrome 的 DevTool,并在 'Settings -> Preferences ...
- 【Web技术】400- 浅谈Shadow DOM
编者按:本文作者:刘观宇,360 奇舞团高级前端工程师.技术经理,W3C CSS 工作组成员. 为什么会有Shadow DOM 你在实际的开发中很可能遇到过这样的需求:实现一个可以拖拽的滑块,以实现范 ...
- JS21. 使用原生JS封装一个公共的Alert插件(HTML5: Shadow Dom)
效果预览 Shadow DOM Web components 的一个重要属性是封装--可以将标记结构.样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净.整 ...
随机推荐
- 【BZOJ 3143】【Hnoi2013】游走 期望+高斯消元
如果纯模拟,就会死循环,而随着循环每个点的期望会逼近一个值,高斯消元就通过列方正组求出这个值. #include<cstdio> #include<cctype> #inclu ...
- hdu1561 树形dp + 背包
#include<cstdio> #include<cstring> #include<iostream> #define INF 999999999 using ...
- Spring POST
Spring POST+表单对象如果数据格式不正确,则页面直接报400.页面没有反应,烦啊
- 【bzoj1853】 Scoi2010—幸运数字
http://www.lydsy.com/JudgeOnline/problem.php?id=1853 (题目链接) 今天考试考了容斥,结果空知道结论却不会写→_→ 题意 求区间中不含6,8两个数字 ...
- POJ1364 King
Description Once, in one kingdom, there was a queen and that queen was expecting a baby. The queen p ...
- 洛谷P1755 斐波那契的拆分
题目背景 无 题目描述 已知任意一个正整数都可以拆分为若干个斐波纳契数,现在,让你求出n的拆分方法 输入输出格式 输入格式: 一个数t,表示有t组数据 接下来t行,每行一个数n(如题) 输出格式: t ...
- PHP邮件注入攻击技术
1. 简介 如 今,互联网的使用急剧上升,但绝大多数互联网用户没有安全知识背景.大多数的人都会使用互联网通过邮件Email的方式和他人进行通信.出于这个原因,大 多数网站允许他们的用户联系他们,向网站 ...
- CF Gym 100685E Epic Fail of a Genie
传送门 E. Epic Fail of a Genie time limit per test 0.5 seconds memory limit per test 64 megabytes input ...
- 将Spark中CompactBuf转换为String
val rdd = sc.textFile("hdfs://hbase11:9000/sparkTsData/ipsoftware/wincc").map{ line => ...
- javaweb学习总结(三十一)——国际化(i18n)
一.国际化开发概述 软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的.符合来访者阅读习惯的页面或数据. 国际化(internationaliz ...