DOM 中文名文档对象模型,英文名 Document Object Model,我们简称为 DOM,是针对 html 和 xml 文档的一种 API,将 html 以一种树状结构呈现出来,可以更直观去研究文档结构,我们将这种树状文档结构称为--DOM 树,或者节点树,一样的概念
一、什么是 DOM?
DOM 中文名文档对象模型,英文名 Document Object Model,我们简称为 DOM,是针对 html 和 xml 文档的一种 API,将 html 以一种树状结构呈现出来,可以更直观去研究文档结构,我们将这种树状文档结构称为--DOM 树,或者节点树,一样的概念
js 通过 dom 节点,可以对文档的 html 标签,属性,css 样式,以及具体的内容做出修改,并对页面中的所有事件进行响应
二、节点树
1.节点类型
- 文档节点--Document
- 标签节点--Element
- 文本节点--Text
- 注释节点--Comment
- 属性节点--Attr
2. 属性
- 节点类型--nodeType
- 节点名称--nodeName
- 节点值--nodeValue
- 子节点--childNodes
- 父节点--parentNodes
- 上一个节点--previousSibling
- 下一个节点--nextSibling
- 第一个子节点--firstChild
- 最后一个子节点--lastChild
3.文档节点--document
(1) 获取
- getElementById()--通过 id 获取元素
<div id="demo">通过 id 获取元素</div>
<script>
var demo = document.getElementById('demo');
demo.onclick = function() {
console.log('通过 id 获取元素')
}
</script>
<!-- 点击 id 为 demo 的元素,控制台输出'通过 id 获取元素' -->
- getElementsByName()--通过 name 获取元素
<input type="text" name="int" value="通过name获取元素1">
<input type="text" name="int" value="通过name获取元素2">
<script>
var int = document.getElementsByName('int');
for(var i = 0;i < int.length; i++) {
console.log(int[i].value);
}
</script>
<!-- 控制台输出 name 为 int 的元素的 value 值 -->
- getElementsByTagName()--通过标签名获取元素
<div>通过标签名获取元素 1</div>
<div>通过标签名获取元素 2</div>
<script>
var div = document.getElementsByTagName('div');
for(var i = 0;i < div.length; i++) {
console.log(div[i].innerHTML)
}
</script>
<!-- 控制台输出标签名为 div 的元素的文本内容 -->
- getElementsByClassName()--通过 class 获取元素
<div class="demo">通过 class 获取元素 1</div>
<div class="demo">通过 class 获取元素 2</div>
<script>
var demo = document.getElementsByClassName('demo');
for(var i = 0;i < demo.length; i++) {
console.log(demo[i].innerHTML)
}
</script>
<!-- 控制台输出 class 为 demo 的元素的文本内容 -->
- querySelector()--通过选择器获取元素
querySelector() 括号里面要跟上符号,class就写.
,id就写#
,标签直接写标签名TagName
<div>通过选择器获取标签名</div>
<div class="div">通过选择器获取 class</div>
<div id="div">通过选择器获取 id</div>
<script>
var divtag = document.querySelector('div');
var divclass = document.querySelector('.div');
var divid = document.querySelector('#div');
divtag.onclick = function() {
console.log('通过选择器获取标签名')
};
// 点击标签 div,控制台输出"通过选择器获取标签名"
divclass.onclick = function() {
console.log('通过选择器获取 class')
};
// 点击 class 为 div,控制台输出"通过选择器获取 class"
divid.onclick = function() {
console.log('通过选择器获取 id')
};
// 点击 id 为 div,控制台输出"通过选择器获取 id"
</script>
- querySelectorAll()--通过选择器获取元素集合
获取的是一个数组集合
<input type="text" value="int1">
<input type="text" value="int2">
<input type="text" value="int3">
<script>
var int = document.querySelectorAll('input')
for(i = 0; i < int.length; i++) {
console.log(int[i].value)
}
</script>
<!-- 浏览器依次打印出`int1`,`int2`,`int3` -->
(2) 创建
- createElement()--创建元素(标签)节点
<ul id="ul"></ul>
<script>
var ul = document.getElementById('ul');
ul.appendChild(document.createElement('li'))
</script>
可以看到,ul 下面已经生成了一个 li 标签
- createTextNode()--创建文本节点
<ul id="ul"></ul>
<script>
var ul = document.getElementById('ul');
var li = ul.appendChild(document.createElement('li'));
var node = document.createTextNode('我是 li');
li.appendChild(node);
</script>
li 标签中生成了一段文本
- createAttribute()--创建属性节点
<input type="text">
<script>
var int = document.getElementsByTagName('input')[0];
var value = document.createAttribute('value');
value.nodeValue = '通过创建属性节点生成';
int.setAttributeNode(value);
</script>
可以看到 value 属性值被成功创建
- createComment()--创建注释节点
<div id="div">创建一个注释节点</div>
<script>
var div = document.getElementById('div');
var comment = document.createComment('添加一个注释节点');
div.appendChild(comment);
</script>
f12 查看源码,可以看到 div 生成一行注释
- createDocumentFragment()--创建文档片段
文档片段的作用,就相当于是添加的所有的节点的父元素
1.假如没有 createDocumentFragment,添加了很多节点,也可以在 dom 上呈现,但是每次添加的时候都会调用一次 appendChild() 方法,产生很多次页面渲染,显得比较臃肿 2.把多次添加的节点放在一个 createDocumentFragment 节点里面,页面只会调用一次就可以把所有的节点都渲染了
-
createEvent()--创建事件对象
-
addEventListener()--添加事件监听函数
-
removeEventListener()--移除事件监听函数
- dispatchEvent()--触发事件
操作 css
<div id="demo">dom</div>
<script>
// 直接通过'.'来操作 style
var demo= document.getElementById('demo');
demo.style.color = 'red';
// 通过 setAttribute() 来创建属性节点
demo.setAttribute('style','background-color: green');
// 通过 style 的 cssText 属性
demo.style.cssText = "border: 10px solid black";
</script>
4.元素节点 (element 对象)
有关 innerHTML, innerText, outerHTML, outerText 的区别
一个是元素内容,一个是文本内容
<div id="div1">第一个 div</div>
<div id="div2">第二个 div</div>
<div id="div3">第三个 div</div>
<div id="div4">第四个 div</div>
<div id="div5"></div>
<div id="div6"></div>
<div id="div7"></div>
<div id="div8"></div>
<script>
var div1 = document.getElementById('div1').innerHTML
console.log(div1) // 第一个 div
var div1 = document.getElementById('div1').outerHTML
console.log(div1) // <div id="div1">第一个 div</div>
var div2 = document.getElementById('div2').innerText
console.log(div2) // 第二个 div
var div2 = document.getElementById('div2').outerText
console.log(div2) // 第二个 div
document.getElementById('div5').innerHTML = '<a>《第 5 个 div》</a>'
// 在原有的标签内增加内容,如果有标签会被识别
document.getElementById('div6').outerHTML = '<a>《第 6 个 div》</a>'
// 原来的标签会被覆盖,新的文本中如果含有标签会自动生成,如果没有标签则直接以文本形式展示
document.getElementById('div7').innerText = '<a>《第 7 个 div》</a>'
// 在原有的标签内增加内容,新标签不会被识别为标签元素,而是被当作文本内容直接写入原标签内
document.getElementById('div8').outerText = '<a>《第 8 个 div》</a>'
// 原来的标签会被覆盖,新标签不会被识别为标签元素,而是直接被当作文本形式展示
</script>
(1) 节点属性
- childElementCount--返回当前元素的子节点的个数
<div id="demo">
<a></a>
<span></span>
<p></p>
<div></div>
</div>
<script>
var demo = document.getElementById('demo')
console.log(demo.childElementCount) // 4
</script>
- firstElementChild--返回当前元素的第一个子元素节点 lastElementChild--返回当前元素的最后一个子元素节点
<div id="demo">
<a></a>
<span></span>
<p></p>
<div></div>
</div>
<script>
var demo = document.getElementById('demo')
console.log(demo.firstElementChild) // <a></a>
console.log(demo.lastElementChild) // <div></div>
</script>
- nextElementSibling--返回当前元素的下一个兄弟元素节点 previousElementSibling--返回当前元素的上一个兄弟元素节点
<span></span>
<div id="demo"></div>
<p></p>
<script>
var demo = document.getElementById('demo')
console.log(demo.nextElementSibling) // <p></p>
console.log(demo.previousElementSibling) // <span></span>
</script>
- 返回当前元素所有的子节点
<div id="demo">
<span></span>
<p></p>
<a></a>
</div>
<script>
var demo = document.getElementById('demo').children
for(var i in demo) {
console.log(demo[i])
}
</script>
控制台查看返回结果
- 返回所有子节点集合
<div id="demo">
<span></span>
<p></p>
<a id="demo1"></a>
</div>
<script>
var demo = document.getElementById('demo').children
for(var i in demo1.childNodes) {
console.log(demo[i])
}
</script>
(2) 节点方法
- appendChild--插入子节点
<div id="demo"></div>
<script>
var demo = document.getElementById('demo')
var node = document.createTextNode('插入一个子节点')
demo.appendChild(node)
</script>
f12 可以看到,div 被插入了一个节点
- insertBefore(a, b)--在指定位置插入节点
参数 a 表示要插入的内容,b 表示定位,在 b 节点之前插入 a 节点
<div id="demo"></div>
<script>
var demo = document.getElementById('demo')
var node = document.createTextNode('插入一个子节点')
demo.appendChild(node)
var hr = document.createElement('hr')
demo.insertBefore(hr, node)
</script>
可以看到,原来的文本节点之前,被添加了一个新的元素节点
- replaceChild(a, b)--替换节点
用参数 a 替换参数 b,a 表示新节点,b 表示旧节点
<div id="demo"></div>
<script>
var demo = document.getElementById('demo')
var node = document.createTextNode('插入一个子节点')
demo.appendChild(node)
var h3 = document.createElement('h3')
var h3node = document.createTextNode('title 标题')
h3.appendChild(h3node)
demo.replaceChild(h3, node)
</script>
h3
是新节点,node
是旧节点,根据图片可以看到,b 替换掉了 a,成功上位
- removeChild--父节点删除子节点
<div id="demo">
<div id="son"></div>
</div>
<script>
var demo = document.getElementById('demo')
var son = document.getElementById('son')
demo.removeChild(son)
</script>
f12 可以看到,id 为 son 的元素节点,通过demo.removeChild()
已经被删除了
- removeAttribute--删除属性节点
<div id="demo" class="div"></div>
<script>
var demo = document.getElementById('demo')
demo.removeAttribute('class')
</script>
class 属性已经被删除了
- 删除文本节点
<div id="demo">文本</div>
<script>
var demo = document.getElementById('demo')
demo.removeChild(demo.childNodes[0])
</script>
通过demo.childNodesp[0]
获取 demo 的第一个节点,即文本节点,然后removeChild
它,就删除了
- isEqualNode--判断两个元素是否
相等
isSameNode--判断两个元素是否相同
两者分别代表
相等
和相同
(1) isEqualNode
相等,指的是两个节点是否是同一类型,具有相等的属性(包括:nodeName, nodeValue…等等),还有相等的 attributes,childNodes(相等的位置包含相同的值)
(2) isSameNode
相同,指的是两个节点引用的是同一个对象
<form action="#">
<input type="button" />
</form>
<form action="#">
<input type="button" />
</form>
<form action="#" id="o">
<input type="button" />
</form>
<form action="#" id="o">
<input type="text" />
</form>
<script>
var forms = document.forms;
var form1 = forms[0];
var form2 = forms[1];
var form3 = forms[2];
var form4 = forms[3];
var _form1 = document.querySelectorAll('form')[0];
console.log(form1.isSameNode(form1)) //true 两个节点引用的对象都是第一个 form
console.log(form1.isSameNode(_form1)) //true 两个节点引用的对象都是第一个 form
console.log(form1.isSameNode(form2)) //false 两个节点引用的不是一个对象
console.log(form1.isEqualNode(form2)) //true 两个节点具有完全等同属性
console.log(form1.isEqualNode(form3)) //false form1 中无等同的 id 属性
console.log(form3.isEqualNode(form4)) //fasle form4 的 childNodes 中的 input 为 text 类别,与 form3 不同
</script>
根据例子代码可以看出区别:
(1) isSameNode
只有引用同一个对象时才相同,比如用两中方法调用同一个对象,再比较这两种方法,比来比去还是那个对象,所以相同
(2) 而isEqualNode
比较两个对象的元素节点是否相等,只要两者一致就可以相等 true
- hasChildNodes()--判断一个元素是否拥有子节点
判断demo
是否拥有子节点,然后输出他的子节点
<div id="demo">
<!-- <a></a> -->
</div>
<script>
var demo = document.getElementById('demo')
console.log(demo.hasChildNodes())
console.log(demo.childNodes)
</script>
- contains(a)--判断一个节点是否包含指定子节点(参数 a 表示要判断的子节点)
存在id="a"
的元素,因此 contains 判断成功输出true
,
不存在id="b"
的元素,因此输出false
<div id="demo">
<a id="a"></a>
<a></a>
</div>
<script>
var demo = document.getElementById('demo')
var a = document.getElementById('a')
console.log(demo.contains(a)) // true
var b = document.getElementById('b')
console.log(demo.contains(b)) // false
</script>
5.属性节点 (Attr 对象)
<input type="text" id="int">
<script>
var int = document.getElementById('int')
// 1.获取属性值
console.log(int.getAttribute("type"))
// text
// 2.获取属性节点
console.log(int.getAttributeNode("type"))
// type="text"
// 3.设置属性值
int.setAttribute("value", "input 框")
// <input type="text" id="int" value="input 框">
// 4.设置属性节点
let name = document.createAttribute("name");
name.nodeValue = "uname";
int.setAttributeNode(name);
console.log(int.getAttributeNode('name').value)
// <input type="text" id="int" value="input 框" name="uname">
// 5.删除属性节点
console.log(int.removeAttribute('name'))
// <input type="text" id="int" value="input 框">
// 6.判断是否存在属性
console.log(int.hasAttributes())
// true
// 7.判断是否存在指定属性
console.log(int.hasAttribute('value'))
// true
</script>
注意:
hasAttribute
和hasAttributes
的区别hasAttributes
判断是否存在属性,hasAttribute
判断是否存在指定属性