關於影子(shadow)DOM

經常寫video,audio等html元素在帶的控制條或者模塊,但是這這些模塊哪裏來的用什麼實現的
在這裏插入圖片描述
發現步驟
在這裏插入圖片描述
進入setttins, 在elements裏勾選
在這裏插入圖片描述
如此打開新世界的大門
在這裏插入圖片描述
隱藏有點深刻,難以發現。

那什麼是影子DOM

  1. 影子dom這個東西的存在,主要解決dom樹建立時能夠實現維護自身邊界的問題。這麼說有點像vue的scope保證自身不會被外來修飾入侵或者污染。
  2. 影子dom將對應的dom信息隱藏起來依然能在html文檔裏渲染出來。但不能通過普通的js方法獲取到dom信息
  3. 影子dom事件捕獲遵從常規dom事件,在影子dom內部依然傳遞,同時也遵從事件冒泡,向整個文檔的dom上傳遞事件。

影子樹和文檔
在這裏插入圖片描述

創建影子樹

通過createShadowRoot創建影子樹root節點

<!DOCTYPE html>
<html>
<head>
	<title>影子dom</title>
	<link rel="dns-prefetch" href="//dfhs.tanx.com">
	<style>
		.box {
			height: 80px;
			width: 80px;
			background-color: red;
		}
	</style>
</head>
<body>
	<div id="box" class="box"></div>
</body>
<script>
	var $box = document.getElementById('box');
	var shadowRoot = $box.createShadowRoot(); // 獲得root
	//var showRoot = $box.webkitGetShadowRoot() // webkit 支持
	var children = document.createElement('div');
	children.setAttribute('style', 'height: 40px; width: 40px; background-color: blue');
	shadowRoot.appendChild(children);
</script>
</html>

效果圖
在這裏插入圖片描述
再給影子樹節點添加css時不能用過class或者元素選擇來添加,否則無效果

<!DOCTYPE html>
<html>
<head>
	<title>影子dom</title>
	<link rel="dns-prefetch" href="//dfhs.tanx.com">
	<style>
		.box {
			height: 80px;
			width: 80px;
			background-color: red;
		}
		.children {
			height: 40px;
			width: 40px;
			background-color: blue;
		}
		div {
			height: 40px;
			width: 40px;
			background-color: blue;
		}
	</style>
</head>
<body>
	<video src="test.mp4" height="200px" controls></video>
	<audio src="mp3.mp3" controls></audio>
	<canvas></canvas>
	<div id="box" class="box"></div>
</body>
<script>
		var $box = document.getElementById('box');
		var shadowRoot = $box.createShadowRoot(); // 獲得root
		//var showRoot = $box.webkitGetShadowRoot() // webkit 支持
		var children = document.createElement('div');
		children.setAttribute('class', 'children');
		shadowRoot.appendChild(children);
</script>
</html>

在這裏插入圖片描述
通過class選擇dom時需要將style也放入影子節點裏

<script>
	var $box = document.getElementById('box');
	var shadowRoot = $box.createShadowRoot(); // 獲得root
	//var showRoot = $box.webkitGetShadowRoot() // webkit 支持
	var children = document.createElement('div');
	children.setAttribute('class', 'children')
	shadowRoot.innerHTML += '<style>.children { height: 40px; width: 40px; background-color: blue;}</style>';
	shadowRoot.appendChild(children);
</script>

不能直接獲得影子DOM

通過js常規方法不能直接獲取到dom節點

	var $box = document.getElementById('box');
	var shadowRoot = $box.createShadowRoot(); // 獲得root
	//var showRoot = $box.webkitGetShadowRoot() // webkit 支持
	var children = document.createElement('div');
	children.setAttribute('class', 'children');
	children.setAttribute('id', 'children');
	shadowRoot.appendChild(children);

	// 獲得影子dom
	// 通過id
	var getShadowRootById = document.getElementById('children');
	console.log(getShadowRootById)
	// 通過節點選擇
	console.log('---------------')
	var getShadowRootByDomBox = document.body.firstChild.nextSibling; // 獲得到box
	//var getShadowRootByDom = getShadowRootByDomBox.firstChild
	var getShadowRootByDom = getShadowRootByDomBox.firstElementChild;
	console.log(getShadowRootByDom)

在這裏插入圖片描述

影子dom事件綁定

在createElement時拿到的元素,添加addEventListener事件

	var $box = document.getElementById('box');
	var shadowRoot = $box.createShadowRoot(); // 獲得root
	//var showRoot = $box.webkitGetShadowRoot() // webkit 支持
	var children = document.createElement('div');
	children.setAttribute('class', 'children')
	shadowRoot.innerHTML += '<style>.children { height: 40px; width: 40px; background-color: blue;}</style>';
	shadowRoot.appendChild(children);

	children.addEventListener('click', function(e) {
		console.log(e)
	})

在這裏插入圖片描述

通過template完整的操縱影子dom

template也是documentfragment

<!DOCTYPE html>
<html>
<head>
	<title>影子dom</title>
	<link rel="dns-prefetch" href="//dfhs.tanx.com">
	<style>
		.box {
			height: 80px;
			width: 80px;
			background-color: red;
		}
		.children {
			height: 40px;
			width: 40px;
			background-color: blue;
		}
	</style>
</head>
<body>
	<div id="box" class="box"></div>
	<div class="box-test"></div>
	<template class="root-tlp">
		<style>
			.test-ctn {
				color: white;
			}
		</style>
		<div>
			<div class="test-ctn" id="test">測試</dt>
		</div>
		<script>
			document.addEventListener('click', function(e) {
				console.log(e)
			})
		</script>
	</template>
</body>
<script>
	var $box = document.getElementById('box');
	var shadowRoot = $box.createShadowRoot(); // 獲得root
	var children = document.createElement('div');
	children.setAttribute('class', 'children')
	shadowRoot.innerHTML += '<style>.children { height: 40px; width: 40px; background-color: blue;}</style>';
	var template = document.querySelector('.root-tlp');
	shadowRoot.appendChild(template.content);
</script>
</html>

在這裏插入圖片描述
當然綁定事件同樣有輸出
在這裏插入圖片描述
利用content元素select屬性將目標內容匹配到template中指定位置,並且目標內容只能在影子元素裏

<!DOCTYPE html>
<html>
<head>
	<title>影子dom</title>
	<link rel="dns-prefetch" href="//dfhs.tanx.com">
	<style>
		.box {
			height: 160px;
			width: 160px;
			background-color: red;
		}
		.children {
			height: 80px;
			width: 80px;
			background-color: blue;
		}
		.test-content {
			background-color: yellow;
		}
	</style>
</head>
<body>
	<div id="box" class="box">
		<div class="test-content">我接着測試</div>
	</div>
	<template class="root-tlp">
		<style>
			.test-ctn {
				color: white;
			}
		</style>
		<div>
			<div class="test-ctn" id="test">測試</dt>
		</div>
		<content select=".test-content"></content>
	</template>
</body>
<script>
	var $box = document.getElementById('box');
	var shadowRoot = $box.createShadowRoot(); // 獲得root
	var children = document.createElement('div');
	var template = document.querySelector('.root-tlp');
	shadowRoot.appendChild(document.importNode(template.content, true));
	document.addEventListener('click', function() {
		console.log('test-content')
	})
</script>
</html>

這種方式改變文檔流順序還能直接獲得dom節點和綁定事件

在這裏插入圖片描述

CSS 選擇器:

:host, :host(), :host-context()
:host

<template class="root-tlp">
		<style>
			.test-ctn {
				color: white;
			}
			:host {
  				font-weight: bold;
			}
		</style>
		<div>
			<div class="test-ctn" id="test">測試</dt>
		</div>
		<content select=".test-content"></content>
	</template>

在這裏插入圖片描述
:host()選擇器,選擇影子dom宿主元素

<body>
	<div id="box" class="box">
		<div class="test-content">我接着測試</div>
	</div>
	<template class="root-tlp">
		<style>
			.test-ctn {
				color: white;
			}
			:host {
  				font-weight: bold;
			}
			:host(.box) {
				color: blue;
			}
		</style>
		<div>
			<div class="test-ctn" id="test">測試</dt>
		</div>
		<content select=".test-content"></content>
	</template>
</body>

在這裏插入圖片描述
:host-context()與後代選擇器表達式一起使用,以僅選擇特定祖先內部的自定義元素的實例

<!DOCTYPE html>
<html>
<head>
	<title>影子dom</title>
	<link rel="dns-prefetch" href="//dfhs.tanx.com">
	<style>
		.box {
			height: 160px;
			width: 160px;
		}
		.children {
			height: 80px;
			width: 80px;
		}
	</style>
</head>
<body>
	<div id="box" class="test">
		<div class="box-content" id="box-content">
			<div class="box-ctn">213</div>
		</div>
	</div>
	<template class="root-tlp">
		<style>
			.test-ctn {
				color: white;
			}
			:host {
  				font-weight: bold;
			}
			:host(.box-content) {
				color: blue;
				background-color:red;
			}
			:host-context(.test) {
				height:  300px;
				background-color: blueviolet
			}
		</style>
		<div>
			<div class="test-ctn" id="test">測試</dt>
		</div>
		<content select=".box-ctn"></content>
	</template>
</body>
<script>
	var $box = document.getElementById('box-content');
	var shadowRoot = $box.createShadowRoot(); // 獲得root
	var children = document.createElement('div');
	var template = document.querySelector('.root-tlp');
	shadowRoot.appendChild(document.importNode(template.content, true));
</script>
</html>

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章