Day4
浏览器
DOM选择器
DOM在创建的时候会自动清除一些错误,比如填补缺失以及关闭标签等
HTML 中的所有内容,甚至注释,都会成为 DOM 的一部分。
<html>
=document.documentElement
最顶层的 document 节点是
document.documentElement
。这是对应<html>
标签的 DOM 节点。<html> <body> <div>Begin</div> <ul> <li>Information</li> </ul> <div>End</div> <script> for (let i = 0; i < document.body.childNodes.length; i++) { alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT } </script> ...more stuff... </body> </html> // childNodes 集合列出了所有子节点,包括文本节点!
对于Dom的使用childNodes所的到的东西实际上是一个集合,因此不能够使用数组的一些方法,但是可以使用for…of…,如果想使用数组方法需要先用Array.from()进行转换数据类型。
(1)兄弟节点
// <body> 的父节点是 <html> alert( document.body.parentNode === document.documentElement ); // true // <head> 的后一个是 <body> alert( document.head.nextSibling ); // HTMLBodyElement // <body> 的前一个是 <head> alert( document.body.previousSibling ); // HTMLHeadElement
(2)纯元素导航
–因为我们不想要文本节点以及注释节点
这些链接和我们在上面提到过的类似,只是在词中间加了
Element
:
children
—— 仅那些作为元素节点的子代的节点。firstElementChild
,lastElementChild
—— 第一个和最后一个子元素。previousElementSibling
,nextElementSibling
—— 兄弟元素。parentElement
—— 父元素。(3) 离得很远的元素如何导航呢?
document.getElementByID()
<div id="elem"> <div id="elem-content">Element</div> </div> <script> // 获取该元素 let elem = document.getElementById('elem'); // 将该元素背景改为红色 elem.style.background = 'red'; </script>
CSS条件筛选元素:querySelectorAll(CSS语法)
<ul> <li>The</li> <li>test</li> </ul> <ul> <li>has</li> <li>passed</li> </ul> <script> let elements = document.querySelectorAll('ul > li:last-child'); for (let elem of elements) { alert(elem.innerHTML); // "test", "passed" } </script>
querySelector(CSS语法)
与上一个方法不同的是,这个方法只会返回满足CSS语法的第一个元素,这样会快一些(因为不需要先找到全部的元素了)
elem.matches(css)
检查元素是否与css选择器的内容匹配,返回true或false
<a href="http://example.com/file.zip">...</a> <a href="http://ya.ru">...</a> <script> // 不一定是 document.body.children,还可以是任何集合 for (let elem of document.body.children) { // 通过['']属性选择器看其属性是否满足要求 if (elem.matches('a[href$="zip"]')) { alert("The archive reference: " + elem.href ); } } </script>
查找元素的祖先:
elem.closest(css)
方法会查找与 CSS 选择器匹配的最近的祖先。elem
自己也会被搜索。<h1>Contents</h1> <div class="contents"> <ul class="book"> <li class="chapter">Chapter 1</li> <li class="chapter">Chapter 2</li> </ul> </div> <script> let chapter = document.querySelector('.chapter'); // LI alert(chapter.closest('.book')); // UL alert(chapter.closest('.contents')); // DIV alert(chapter.closest('h1')); // null(因为 h1 不是祖先) </script>
换句话说,方法
closest
在元素中得到了提升,并检查每个父级。如果它与选择器匹配,则停止搜索并返回该祖先。[而且方法中必须有参数]老版的多条件查询:
elem.getElementsByTagName(tag)
查找具有给定标签的元素,并返回它们的集合。tag
参数也可以是对于“任何标签”的星号"*"
。
elem.getElementsByClassName(className)
返回具有给定CSS类的元素。
document.getElementsByName(name)
返回在文档范围内具有给定name
特性的元素。很少使用。其中老版的查询是返回的实时集合,但是querySelectorAll返回的是静态集合
总结
节点属性:type,tag和content.
nodeType
属性提供了另一种“过时的”用来获取 DOM 节点类型的方法。它有一个数值型值(numeric value):
- 对于元素节点
elem.nodeType == 1
,- 对于文本节点
elem.nodeType == 3
,- 对于 document 对象
elem.nodeType == 9
,- 在 规范 中还有一些其他值。
给定一个 DOM 节点,我们可以从
nodeName
或者tagName
属性中读取它的标签名:alert( document.body.nodeName ); // BODY alert( document.body.tagName ); // BODY
且在在 HTML 模式下,
tagName/nodeName
始终是大写的:它是BODY
,而不是<body>
或<BoDy>
。innerHTML
innerHTML修改后会完全重写之前的内容。因此
+=
是不被允许的。outerHTML
注意:与
innerHTML
不同,写入outerHTML
不会改变元素。而是在 DOM 中替换它。<div>Hello, world!</div> <script> let div = document.querySelector('div'); // 使用 <p>...</p> 替换 div.outerHTML div.outerHTML = '<p>A new element</p>'; // (*) // 蛤!'div' 还是原来那样! alert(div.outerHTML); // <div>Hello, world!</div> (**) </script>
所以,在
div.outerHTML=...
中发生的事情是:
div
被从文档(document)中移除。- 另一个 HTML 片段
<p>A new element</p>
被插入到其位置上。div
仍拥有其旧的值。新的 HTML 没有被赋值给任何变量。textContent
大多数场景是写入场景,不同与innerHTML写入假如带有标签形式·
<h1>hhh</h1>
这样的形式会被渲染对应的元素,textContent会直接将其作为文本,不会被渲染成对应标签。<div id="elem1"></div> <div id="elem2"></div> <script> let name = prompt("What's your name?", "<b>Winnie-the-Pooh!</b>"); elem1.innerHTML = name; elem2.textContent = name; </script> 第一个 <div> 获取 name “作为 HTML”:所有标签都变成标签,所以我们可以看到粗体的 name。 第二个 <div> 获取 name “作为文本”,因此我们可以从字面上看到 <b>Winnie-the-Pooh!</b>。
hidden
在js里面可给对应元素加.hidden来隐藏元素,作用与
display: none
效果一致
特性与属性
特性是DOM的标准的特性去创建DOM属性
请注意,一个元素的标准的特性对于另一个元素可能是未知的。例如
"type"
是<input>
的一个标准的特性(HTMLInputElement),但对于<body>
(HTMLBodyElement)来说则不是。规范中对相应元素类的标准的属性进行了详细的描述。<body id="body" type="..."> <input id="input" type="text"> <script> alert(input.type); // text alert(body.type); // undefined:DOM 属性没有被创建,因为它不是一个标准的特性 </script> </body>
访问特性的方法:(操作的是HTML里面的内容)
elem.hasAttribute(name)
—— 检查特性是否存在。elem.getAttribute(name)
—— 获取这个特性值。elem.setAttribute(name, value)
—— 设置这个特性值。elem.removeAttribute(name)
—— 移除这个特性。<body something="non-standard"> <script> alert(document.body.getAttribute('something')); // non-standard </script> </body> // 读取的非标准特性
属性:
一般来说特性修改属性是可以的,属性反过来修改特性也是可以。但是input.value只可以通过特性同步到属性,反之是不被允许的。
<input> <script> let input = document.querySelector('input'); // 特性 => 属性 input.setAttribute('value', 'text'); alert(input.value); // text // 这个操作无效,属性 => 特性 input.value = 'newValue'; alert(input.getAttribute('value')); // text(没有被更新!) </script>
在上面这个例子中:
改变特性值
value
会更新属性。但是属性的更改不会影响特性。
多出现于Vue的特性:data-xxx
例如,如果一个
elem
有一个名为"data-about"
的特性,那么可以通过elem.dataset.about
取到它。当然也可以使用getArribute(xxx)
修改文档
创建一个元素
// 1. 创建 <div> 元素 let div = document.createElement('div'); // 2. 将元素的类设置为 "alert" div.className = "alert"; // 3. 填充消息内容 div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";
插入文档
对此有一个特殊的方法
append
:document.body.append(div)
。<style> .alert { padding: 15px; border: 1px solid #d6e9c6; border-radius: 4px; color: #3c763d; background-color: #dff0d8; } </style> <script> let div = document.createElement('div'); div.className = "alert"; div.innerHTML = "<strong>Hi there!</strong> You've read an important message."; document.body.append(div); </script>
这里是更多的元素插入方法,指明了不同的插入位置:
node.append(...nodes or strings)
—— 在node
末尾 插入节点或字符串,
node.prepend(...nodes or strings)
—— 在node
开头 插入节点或字符串,上面的针对的是node里面的内容进行作用
node.before(...nodes or strings)
—— 在node
前面 插入节点或字符串,
node.after(...nodes or strings)
—— 在node
后面 插入节点或字符串,
node.replaceWith(...nodes or strings)
—— 将node
替换为给定的节点或字符串。还有一种插入方法(更通用)
为此,我们可以使用另一个非常通用的方法:
elem.insertAdjacentHTML(where, html)
。该方法的第一个参数是代码字(code word),指定相对于
elem
的插入位置。必须为以下之一:
"beforebegin"
—— 将html
插入到elem
之前,"afterbegin"
—— 将html
插入到elem
开头,"beforeend"
—— 将html
插入到elem
末尾,"afterend"
—— 将html
插入到elem
之后。
节点移除
想要移除一个节点,可以使用
node.remove()
。克隆节点
调用
elem.cloneNode(true)
来创建元素的一个“深”克隆 —— 具有所有特性(attribute)和子元素。如果我们调用elem.cloneNode(false)
,那克隆就不包括子元素。