<一>从了解到掌握DOM,轻松get知识点

382 阅读6分钟

一、DOM介绍

DOM 是document object model ,文档对象模型:

  • D(document):document的意思是文档,在dom中会将HTML这个页面给解析为一个文档,并在解析的同时会提供一个 document对象。

    document对象:每个载入浏览器的HTML文档都会成为document对象,使我们可以从脚本中对HTML页面中的所有元素进行访问,因为document对象是window对象的一部分,所以也可通过window.doucument进行访问。

  • O(object):object就是对象,相必大家对于这个都不陌生,而DOM则把HTML页面中的所有元素都解析为一个对象。

  • M(model):M代表的就是model(模块),主要表现的是dom里面各个对象之间的关系。

它是W3C 制定的浏览器提供的对HTML文档操作的接口,把文档中的代码内容翻译成一个对象模型,在这个模型中,所有相关的标签属性注释文本等等12种数据,都翻译为一种类型的对象,统称节点对象,节点对象之间,在文档模型数据结构中存在某种关系:根节点 父子节点 同胞节点等等。

根据 DOM规定,HTML 文档中的每个成分都是一个节点。(一棵节点树中的所有节点彼此都是有关系的。

  • 整个文档是一个文档节点(nodeType为9)
  • 每个 HTML 标签/body标签是一个元素节点(nodeType为1)
  • 包含在 HTML 元素中的文本是文本节点(如换行、包裹在html标签中的文本 nodeType为3)
  • 每一个 HTML 属性是一个属性节点(nodeType为2)
  • 注释属于注释节点(nodeType为8)

例如下代码:

<html>
  <head>
    <title>DOM Tutorial</title> 
  </head> 
  <body> 
    <h1>DOM Lesson one</h1> 
    <p>Hello world!</p> 
  </body> 
</html>
<!-- 
	1. <head> 和 <body> 的父节点是 <html> 节点,文本节点 "Hello world!" 的父节点是 <p> 节点。
 	2. 大部分元素节点都有子节点。比方说,<head> 节点有一个子节点:<title> 节点。<title> 节点也有一个子节点:文本节点 "DOM Tutorial"。
	3. 当节点分享同一个父节点时,它们就是同辈(同级节点)。比方说,<h1> 和 <p>是同辈,因为它们的父节点均是 <body> 节点。
	4. 节点也可以拥有后代,后代指某个节点的所有子节点,或者这些子节点的子节点,以此类推。比方说,所有的文本节点都是 <html>节点的后代,而第一个文本节点是 <head> 节点的后代。
	5. 节点也可以拥有先辈。先辈是某个节点的父节点,或者父节点的父节点,以此类推。比方说,所有的文本节点都可把 <html> 节点作为先辈节点。
-->

注意:

  1. 只有一个根节点document
  2. 除了根节点外,其他所有节点都有唯一的一个父节点
  3. document是window对象的属性
  4. 元素的属性/文本/注释也是独立节点,注意属性节点 不是元素节点的子节点 二、获取元素的方式

1、旧方法 --- html4

(1)document.getElementById根据ID获取 最快

const boxtest1 = document.getElementById('div1');
console.log(boxtest1);
console.log(div1); // 注意:不建议直接用id获取元素

(2)document.getElementsByClassName 根据类名获取多个,取某一个值加[下标] HTMLCollection

const boxtest2 = document.getElementsByClassName('box1');
console.log(boxtest2);
boxtest2.forEach((i) => { 
       console.log(i);
})    //boxtest2.forEach is not a function

问:HTMLCollection没有forEach方法可以遍历吗???????????

答:可以。

注意:NodeList有forEach方法 也可以用for

for(let i = 0; i < boxtest2.length; i++) {
        console.log(boxtest2[i]);
}

据标签名获取 多个 取某一个值加[下标] NodeList

const boxtest3 = document.getElementsByTagName('div');
console.log(boxtest3);
console.log(boxtest3[0]);

据标签的name属性获取 NodeList 多个 通过下标获取某一个节点

const boxtest4 = document.getElementsByName('www');
console.log(boxtest4[1]);
2、 H5新方法—参数是选择器
const boxtest5 = document.querySelector('div'); // 单个 满足条件的第一个
console.log(boxtest5);
const boxtest6 = document.querySelectorAll('div'); // 多个 满足条件的集合 NodeList [下标]获取某一个节点
console.log(boxtest6);

三、链式获取元素

1、获取父元素(元素节点对象) 再通过父元素获取子元素
const son1 = document.getElementsByTagName('div')[0].getElementsByClassName('son')[0];
console.log(son1);
const son2 = document.getElementsByClassName('fa')[0].getElementsByTagName('div')[0];
console.log(son2);
onst son3 = document.getElementsByClassName('fa')[0].getElementsByName('nametest')[0];
console.log(son3); // 报错
const son4 = document.getElementsByTagName('div')[0].getElementById('boxson');
console.log(son4); // 报错
const son5 = document.getElementsByName('uuu')[0].getElementsByTagName('div')[0];
console.log(son5);

(1) 获取多个时,哪怕满足条件的只有一个元素,返回也是一个集合

const son1 = document.getElementsByTagName('div');

(2) 获取多个时,满足条件的都能被获取到

const son1 = document.getElementsByClassName('a');
console.log(son1);

总结:getElementsByName getElementById不能在元素节点上调用

四、系统提供的直接获取元素的方法

    <form action=""></form>
    <form action=""></form>
    <img src="" alt="">
    <img src="" alt="">
    <a href=""></a>

    console.log(document.body); // body元素
    console.log(document.forms); // form表单
    console.log(document.images); // img元素
    console.log(document.links); // a标签
    console.log(document.URL); // 地址
    console.log(document.documentElement); // 根节点

    console.log(document.all); // 所有的元素节点
    // console.dir(document);
    console.log(document.getElementsByTagName("*"));
    console.log(document.querySelectorAll("*"));

五、关系获取元素

HTML:
        <div class="content">
        <div class="sn0"></div>
        333
        <div class="sn1">
            <p>2222</p>
        </div>
        999
        <img src="" alt="" class="img1">
        <img src="" alt="">
        <div class="sn2"></div>
    </div>
    <div class="header_Img">
        sss
        <div class="header_txt">sss</div>
        <div class="header_nickname"></div>
        666
    </div>
    <ul>
        <li>选项1</li>
        <li>选项2</li>
        <li>选项3</li>
        <li>选项4</li>
        <li>选项5</li>
    </ul>

	// 子级找父级
        const header_txt = document.getElementsByClassName('header_txt')[0];
        console.log(header_txt.parentElement); // 父元素
        console.log(header_txt.parentNode); // 父节点

	// 父级找子级
        const header_Img = document.getElementsByClassName('header_Img')[0];
        console.log(header_Img.children); // 子元素们(元素节点)
        console.log(header_Img.childNodes); // 子节点们(所有节点)

        console.log(header_Img.firstElementChild); // 第一个子元素
        console.log(header_Img.firstChild); // 第一个子节点

        console.log(header_Img.lastElementChild); // 最后一个子元素(跳过其他节点, 找元素节点)
        console.log(header_Img.lastChild); // 最后一个子节点(不跳过其他类型节点)

        // 兄弟
        const sn1 = document.querySelector('.sn1');
        console.log(sn1.nextElementSibling); // 下一个元素
        console.log(sn1.nextSibling); // 下一个节点

        console.log(sn1.previousElementSibling); // 上一个元素
        console.log(sn1.previousSibling); // 上一个节点
    
    练习1:通过.content找到p
        const content = document.querySelector('.content');
        // console.log(content.children[1].children[0]);
        // console.log(content.children[1].firstElementChild);
        // console.log(content.children[1].lastElementChild);
        // console.log(content.firstElementChild.nextElementSibling.firstElementChild);
        console.log(content.firstElementChild.nextElementSibling.lastElementChild);
    练习2:通过li找到body
        // const li0 = document.querySelector('li');
        const li0 = document.querySelectorAll('li')[0];
        // console.log(li0.parentElement.parentElement);
        // console.log(li0.parentNode.parentNode);
        console.log(li0.parentNode.previousElementSibling.parentNode);

        console.log(li0.parentNode.previousElementSibling.lastElementChild);

六、节点的创建、添加、删除

1、创建节点
const div1 = document.createElement('div');
const div2 = document.createElement('div');
2、添加节点

(1)append 与 appendChild (在父元素添加子节点)

document.body.appendChild(div1);
document.body.append(div1);

append appendChild区别

1. append可以添加文本节点 appendChild只接受节点对象
document.body.append('这是txt');
document.body.appendChild('这是txt');

2. append可以一次性添加多个节点 appendChild不可以
document.body.append('这是txt1', '这是text2', div1);
document.body.appendChild(div1, div2);

3. append没有返回值 appendChild返回值为添加的对象
console.log(document.body.appendChild(div1));
console.log(document.body.append(div1));

(2)添加节点 insertBefore(要添加的节点, 要在哪个元素之前添加)

document.body.insertBefore(div2, document.getElementById('divs'));
3、克隆节点

el.cloneNode(); 参数:true/false true:包含子节点 false:不包含 默认false

(1)克隆html中已存在的id为divs的div节点 静态的

var res = document.getElementById('divs').cloneNode(true);
console.log(res);
document.body.append(res);

(2)克隆自己创建的节点

const p1 = document.createElement('p');
var res1 = p1.cloneNode();
document.body.append(res1);
4、向自己创建的节点中添加节点
const div1 =  document.createElement('div');
const p2 = document.createElement('p');
div1.appendChild(p2);
document.querySelector('.son').appendChild(div1);
5、创建文本节点(了解)

创建一行文字,文本节点,创建一个div元素,将文本节点放入div中,再将div放到body中

const txt = document.createTextNode('文本节点'); // 文本节点对象
const div = document.createElement('div'); // 元素节点对象
//div.append(txt);
div.appendChild(txt);
document.body.append(div);
console.log(typeof txt);

// console.log(document.body.innerHTML);
// console.log(typeof document.body.innerHTML);
// document.body.innerHTML += '这是拼接上的字符串';
document.body.innerHTML += '<div>这是拼接上的字符串</div>';
6、节点删除
通过父元素删除子元素
document.getElementById('divs').removeChild(document.getElementsByClassName('son1')[0]);
const fa = document.getElementById('divs');
fa.removeChild(fa.firstElementChild);
通过元素自己直接删除
document.getElementsByClassName('son1')[0].remove();
替换元素(了解)
const p1 = document.createElement('p');
fa.replaceChild(p1, document.getElementsByClassName('son1')[0]);

七、节点内容的增删查改

HTML:
<div class="content">
        如果
        <div class="left">left-content</div>
        <div class="right">
            right-content
            <div class="right-top">
                right-top
            </div>
        </div>
        if
    </div>
    <div class="data">
        <div class="">0</div>
</div>

JavaScript:
	// 1. 节点内容的获取 - 查找
        console.log(document.querySelector('.content').innerHTML);
        console.log(document.querySelector('.content').innerText);

        // 2. 新增
        // document.querySelector('.content').innerHTML += '<p>新增文本</p>';
        document.querySelector('.content').innerText += '<p>innerText-新增</p>'; 

        // 3. 修改
        // document.querySelector('.content').innerHTML = '<div>www</div>';
        // document.querySelector('.content').innerText = '<div>www</div>';

        // 4. 删除/ 清空
        // document.querySelector('.content').innerHTML = '';
        document.querySelector('.content').innerText = '';

        // 5. innerHTML innerText的区别
        // a. innerHTML获取的是标签之间的所有内容 innerText只获取标签(包括子元素)之间的文本内容
        // b. innerHTML里面写标签的字符串 可以被识别为标签, innerText里面写标签字符串 识别为字符串
        // c. innerHTML+=赋值 可以拼接字符串和标签 但是innerText+= 会将标签原有的元素过滤掉

        // 注意:innerHTML innerText 都是字符串
将后端的数据显示到页面上
    var sss = [1, 2, 3, 4];
    var str = '';
    for(var i = 0; i < sss.length; i++) {
      str += `<div>${sss[i]}</div>`; //  undefined<div>1</div> + <div>2</div>
    }
    console.log(str);
    // var sss1 =  `<div>${sss[0]}</div>
    // <div>${sss[1]}</div>
    // <div>${sss[2]}</div>
    // <div>${sss[3]}</div>`;
    // console.log(sss1);

    document.getElementsByClassName('data')[0].innerHTML += str;
    var w; // undefined
    var str = 'lll';
    console.log(w + str); // 进行字符串的拼接 undefinedlll

八、节点的标准属性的增删查改

HTML:
    <div class="box1" id="div1" style="color: red;">这是div标签</div>
    <input type="text" value="999" name="username">
    <br><br>
    <input type="password" name="password" id="" value="123456">
    <br><br>
    <input type="radio" name="sex" id="" value="1" checked>
    <br><br>
    <input type="checkbox" name="hobby" id="" value="2" checked>
    <br><br>
    <img src="./imgs/baidu.png" alt="">
    
JavaScript:
	// 获取
        const div1 = document.querySelector('#div1');
        console.log(div1.id, div1.style);
        // 驼峰命名

        const input1 = document.querySelectorAll('input');
        console.log(input1[0].value);
        console.log(input1[1].value);
        console.log(input1[2].value);
        console.log(input1[3].value);
        // {username: '999', password: '123456', sex: 1, hobby: [1, 2, 3]}

        console.log(input1[2].checked);
        console.log(input1[3].checked);

        const imgwww = document.querySelector('img');
        console.log(imgwww.src);

        // 修改
        // imgwww.src = './imgs/baidu1.png';

        // 新增
        div1.style.backgroundColor = 'red';

        // 删除
        div1.style.backgroundColor = '';

待续......