Dom

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口(API)。 (DOM就是用来处理HTML机构)。

节点

加载HTML页面时,web浏览器生成一个树型结构,用来表示页面内部结构,称之为DOM树,DOM将这种树型结构理解为由节点组成。

节点属性

nodeType(节点类型) nodeName(节点名称) nodeValue(节点值)
1(元素节点) 大写的标签名 null
3(文本节点) #text 文本内容
8(注释节点) #comment 注释内容
9(文档节点) #document null

获取子节点

Tip:是属性,不是方法。

  • 父亲节点.children; 获取直接元素子节点。注:即nodeType==1的元素节点。
  • 父亲节点.childNodes; 获取直接子节点 (和结构相关结构边了这个集合也会改变:比如去掉空格或者换行就相当于去掉了文本节点text)。
  • 获取子节点,获取到了就是一个类数组集合,获取不到就是空集合。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ul id="ul1">
<li>1</li>
<li>2</li>
<li>
<ul>
<li>3.1</li>
<li>3.2</li>
<li>3.3</li>
</ul>
</li>
<li>4</li>
<li>5</li>
<p></p>
</ul>

var oUl = document.getElementById('ul1');
var olis = oUl.children;
var olis2 = oUl.childNodes;
console.log(olis);
console.log(olis2);

输出

可以通过节点属性获取到想要的节点,比如P节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        <ul id="ul1">
<li>1</li>
<li>2</li>
<li>
<ul>
<li>3.1</li>
<li>3.2</li>
<li>3.3</li>
</ul>
</li>
<li>4</li>
<li>5</li>
<p></p>
</ul>
</body>
<script>
var oUl = document.getElementById('ul1');
var olis = Array.from(oUl.children);
var oP="";
olis.forEach(ele=>{
if(ele.nodeName=="P"){
oP=ele;
}
});
console.log(oP); //<p></p>

获取父节点

Tip:是属性,不是方法。

  • parentNode; 获取直接父节点 获取不到是null。
  • offsetParent; 获取已经定位的父集元素,如果说没有已经定位的父集元素获取到的就是body。
  • 获取到的还是一个元素节点,所以可以链式操作=>test2.parentNode.parentNode。
  • 获取到的是一个元素对象(具体的节点),获取不到就是null。
1
2
3
4
5
6
7
8
9
10
11
12
    <div id="test">
<div id="test1">
<div id="test2"></div>
</div>
</div>
var test2 = document.getElementById('test2');
console.log(test2.parentNode);
/*
<div id="test1">
<div id="test2"></div>
</div>
*/

节点的其他获取方式

  • 带Element的就是元素节点;不带的就是节点(基本都是文本节点#text)
  • firstElementChild: 获取第一个元素子节点(不兼容:IE8及以下没有这个属性 ->undefined)
  • firstChild:获取第一个子节点
  • lastElementChild:获取最后一个元素子节点(不兼容:IE8及以下没有这个属性 ->undefined)
  • lastChild:获取最后一个子节点
  • previousElementSibling:获取上一个相邻元素节点(不兼容:IE8及以下没有这个属性 ->undefined)
  • previousSibling:获取上一个相邻节点
  • nextElementSibling:获取下一个相邻元素节点(不兼容:IE8及以下没有这个属性 ->undefined)
  • nextSibling:获取下一个相邻节点

节点的操作

节点的操作就包含了创建、添加、插入、替换、移除与克隆;

插入元素的方式如下:(可一下传入多个)

  • node.append(…nodes or strings)——在node下一级末尾插入节点或字符串;

  • node.prepend(…nodes or strings)——在node下一级开头插入节点或字符串;

  • node.before(…nodes or strings)——在node同级前面插入节点或字符串;

  • node.after(…nodes or strings)——在node同级后面插入节点或字符串;

  • node.replaceWith(…nodes or strings)——将node替换为给定的节点或字符串;

  • node.remove()——将node移除;

  • node.cloneNode(boolean)——将node克隆;

    • boolean默认为false,只会clone本身;
    • boolean设置为true,深度克隆,子元素也会克隆;
  • 添加:

1
2
3
4
<div class="box">
<span>hhaa </span>
<p>hhee</p>
</div>
1
2
3
4
5
6
7
8
9
const box = document.getElementsByClassName("box")[0];

// 创建一个DOM对象
const h2El = document.createElement("h2");
h2El.className = "title";
h2El.classList.add("active");
h2El.textContent = "我是标题";

box.append(h2El);

执行结果为:

1
2
3
4
5
<div class="box">
<span>hhaa </span>
<p>hhee</p>
<h2 class="title active">我是标题</h2>
</div>

旧的节点操作方法

在很多地方我们也会看到一些旧的操作方法:**(不推荐使用)**

  • parentElem.appendChild(node):在parentElem的父元素最后位置添加一个子元素;
  • parentElem.insertBefore(node, nextSibling):在parentElem的nextSibling前面插入一个子元素;
  • parentElem.replaceChild(node, oldChild):在parentElem中,新元素替换之前的oldChild元素;
  • parentElem.removeChild(node):在parentElem中,移除某一个元素;

操作元素结构上的属性

ps:color属性是style里的呀,所以style里面的属性用的是xxx.style.xxx;别的用的Attribute;

attribute

  • 标准的attribute:某些attribute属性是标准的,比如id、class、href、type、value等;
  • 非标准的attribute:某些attribute属性是自定义的,比如abc、age、height等;
1
<div id="myDiv" class="mydivClass" age="18" height="188"></div>

对于所有的attribute访问都支持如下的方法:

  • 元素对象.hasAttribute(attr);检查是否存在 返回boolean值;
  • 元素对象.setAttribute(attr,val); 设置
  • 元素对象. getAttribute(attr);获取
  • 元素对象.removeAttribute(attr);移除

attribute具备以下特征:

  • 它们的名字是大小写不敏感的(id与ID相同);
  • 它们的值总是字符串类型的;

property

对象.属性的方式;

  • 对于标准的attribute,会在DOM对象上创建与其对应的property属性:
  • 对于非标准的attribute,为undefined
  • 除非特别情况,大多数情况下,设置、获取attribute,推荐使用property的方式:
1
<div id="myDiv" class="mydivClass" age="18" height="188"></div>
1
2
3
4
5
const myDiv = document.getElementById('myDiv');
console.log(myDiv.hasAttribute('HEIGHT')); // true(对小大写不敏感)
console.log(myDiv.id); // myDiv
console.log(myDiv.className); // mydivClass (class要用className)
console.log(myDiv.age); // undefined

data-*自定义属性

HTML5的data-*自定义属性,那么它们也是可以在dataset属性中获取到的:

1
<div id="myDiv" class="mydivClass" data-age="18" data-height="188"></div>
1
2
3
const myDiv = document.getElementById('myDiv');
console.log(myDiv.dataset.age); // 18
console.log(myDiv.dataset.height); //188

JavaScript动态修改样式

其实用到了property,通过.style 的方式来修改;(即:标签有标准的attribute:style);

常规写法

JS动态修改样式,要是修改的样式很多,用JS修改,后期不移维护;

1
<div id="myDiv" class="mydivClass" age="18">fsllala</div>
1
2
3
4
5
6
7
8
9
10
11
/**
* 点击div动态修改样式
*
* 缺陷:要是修改的样式很多,用JS修改,后期不移维护;
*/
const myDiv = document.getElementById('myDiv');
myDiv.onclick = () => {
myDiv.style.color = "red";
myDiv.style.fontSize = "24px";
myDiv.style.background = "orange";
}

className

通过className来动态修改样式,它会替换整个class中的字符串;

元素的class attribute,对应的property并非叫class,而是className;

这是因为JavaScript早期是不允许使用class这种关键字来作为对象的属性,所以DOM规范使用了className;

1
<div id="myDiv" class="mydivClass" age="18">fsllala</div>
1
2
3
4
5
.active {
color: red;
background-color: antiquewhite;
font-size: 24px;
}
1
2
3
4
const myDiv = document.getElementById('myDiv');
myDiv.onclick = () => {
myDiv.className = "active";
}

执行完后,检查dom元素,可以看到原来的class被替换掉了;

1
<div id="myDiv" class="active" age="18">fsllala</div>

classList

同className替换class名相比,如果我们需要添加或者移除单个的class,那么可以使用classList属性。

  • elem.classList是一个特殊的对象:
    • elem.classList.add(class):添加一个类;
    • elem.classList.remove(class):添加/移除类;
    • elem.classList.toggle(class):如果类不存在就添加类,存在就移除它;
    • elem.classList.contains(class):检查给定类,返回true/false;
  • classList是可迭代对象,可以通过for of进行遍历;

将文章上方的className替换成classList.add:

1
2
3
4
const myDiv = document.getElementById('myDiv');
myDiv.onclick = () => {
myDiv.classList.add("active");
}

执行完后,检查dom元素,可以看到原来的class后面添加了新的class名为 active ;

1
<div id="myDiv" class="mydivClass active" age="18">fsllala</div>

getComputedStyle

如果我们需要读取样式:

  • 对于内联样式,是可以通过style.*的方式读取到的;

  • 对于style、css文件中的样式,是读取不到的;

这个时候,我们可以通过getComputedStyle的全局函数来实现:

1
<div id="myDiv" class="active" age="18" style="font-weight: 900;">fsllala</div>
1
2
3
4
5
.active {
color: red;
background-color: antiquewhite;
font-size: 24px;
}
1
2
3
4
5
6
const myDiv = document.getElementById('myDiv');
myDiv.onclick = () => {
console.log(myDiv.style.color); // 空
console.log(myDiv.style.fontWeight); // 900
console.log(getComputedStyle(myDiv).fontSize);// 24px
}