DOM,全称Document Object Model,中文翻译为文档对象模型。DOM属于Web API的一部分。Web API中定义了非常多的对象,通过这些对象可以完成对网页的各种操作(添加删除元素、发送请求、操作浏览器等)。什么是DOMDOM中的D意为Document,即文档。所谓文档就是指整个网页,换言之,DOM是用来操作网页的。O意为Object,即对象。DOM将网页中的每一部分内容都转换为了对象,div有div的对象,input有input的对象,甚至一段文本,一段注释也有其所对应的对象。转换为对象干什么?还记得面向对象吗?转换对象以后,我们就可以以面向对象的方式去操作网页,想要操作哪个元素就获取哪个元素的对象,然后通过调用其方法或属性完成各种操作。M意为Model,即模型。模型用来表示对象之间的关系,也就是父子元素、祖先后代、兄弟元素等,明确关系后我们便可以通过任意一个对象去获取其他的对象。<!DOCTYPE html> <html lang="zh"> <head> <title>My Title</title> </head> <body> <h1>A Heading</h1> <a href="#">Link Text</a> </body> </html>>概念节点(Node)在DOM标准下,网页中的每一个部分都会转换为对象。这些对象有一个共同的称呼——节点(Node)。一个页面将会由多个节点构成,虽然都称为节点,但是它们却有着不同的类型:文档节点元素节点文本节点属性节点…每一个节点都有其不同的作用,文档节点表示整个网页,元素节点表示某个标签,文本节点表示网页中的文本内容,属性节点表示标签中的各种属性。如果从对象的结构上来讲,这些对象都有一个共同的父类Node。总的来说,都是属于节点,但是具体类型不同。关系祖先 —— 包含后代元素的元素是祖先元素后代 —— 被祖先元素包含的元素是后代元素父 —— 直接包含子元素的元素是父元素子 —— 直接被父元素包含的元素是子元素兄弟 —— 拥有相同父元素的元素是兄弟元素小试牛刀要使用DOM来操作网页,我们需要浏览器至少得先给我一个对象,才能去完成各种操作。所以浏览器已经为我们提供了一个document对象,它是一个全局变量可以直接使用,document代表的是整个的网页。<button id="btn">点我一下</button> <script> // 获取btn对象 const btn = document.getElementById("btn") // 修改btn中的文字 btn.innerText = "Click ME" </script>>文档节点(document)document对象表示的是整个网页document对象的原型链HTMLDocument -> Document -> Node -> EventTarget -> Object.prototype -> null凡是在原型链上存在的对象的属性和方法都可以通过Document去调用部分属性:document.documentElement --> html根元素 document.head --> head元素 document.title --> title元素 document.body --> body元素 document.links --> 获取页面中所有的超链接 ...>元素节点(element)在网页中,每一个标签都是一个元素节点如何获取元素节点对象?通过document对象来获取元素节点通过document对象来创建元素节点通过document来获取已有的元素节点:document.getElementById()根据id获取一个元素节点对象<button id="btn">点我一下</button> <script> const btn = document.getElementById("btn") console.log(btn) </script>document.getElementsByClassName()根据元素的class属性值获取一组元素节点对象<span class="s1">我是span</span> <span class="s1">我是span</span> <span class="s1">我是span</span> <span class="s1">我是span</span> <span class="s1">我是span</span> <script> // 返回的是一个类数组对象,该方法返回的结果是一个实时更新的集合 // 当网页中新添加元素时,集合也会实时的刷新。 const spans = document.getElementsByClassName("s1") console.log(spans) // HTMLCollection(5) [span.s1, span.s1, span.s1, span.s1, span.s1] for (let i = 0; i < spans.length; i++) { spans[i].innerText = "我是span"+i } </script>document.getElementsByTagName()根据标签名获取一组元素节点对象<div>我是div</div> <div>我是div</div> <div>我是div</div> <div>我是div</div> <div>我是div</div> <script> // 返回的结果是可以实时更新的集合 const divs = document.getElementsByTagName("div") // document.getElementsByTagName("*") 获取页面中所有的元素 const divs = document.getElementsByTagName("*") console.log(divs) // HTMLCollection(5) [div, div, div, div, div] </script>document.getElementsByName()根据name属性获取一组元素节点对象<form> <input type="text" name="username"> <input type="radio" name="gender" value="male"> 男 <input type="radio" name="gender" value="female"> 女 </form> <script> // 返回一个实时更新的集合,主要用于表单项。 const genderInput = document.getElementsByName("gender") console.log(genderInput) // NodeList(2) [input, input] </script>document.querySelectorAll()根据选择器去页面中查询元素<div>我是div</div> <div>我是div</div> <div>我是div</div> <script> // 会返回一个类数组(不会实时更新) const divs2 = document.querySelectorAll("div") console.log(divs2) // NodeList(3) [input, input,input] </script>document.querySelector()根据选择器去页面中查询第一个符合条件的元素<div>我是div</div> <div>我是div</div> <script> // 会返回一个类数组(不会实时更新) const div = document.querySelector("div") // .xx | #xx console.log(divs2) // NodeList(2) [input,input] </script>创建一个元素节点document.createElement()根据标签名创建一个元素节点对象const h2 = document.createElement("h2") // 创建了H2,但未添加>元素的属性和方法<div id="box1">我是box1 </div> <script> const box1 = document.getElementById("box1") cosole.log(box1.__proto__) </script>div的原型链HTMLDivElement -> HTMLElement -> Element -> Node -> ...element.childNodes 获取当前元素的子节点(会包含空白的子节点)<div id="box1"> 我是box1 <span class="s1">我是s1</span> <span class="s1">我是s1</span> </div> <script> const box1 = document.getElementById("box1") const cns = box1.childNodes console.log(children.length) // 输出:5 包含空格 </script>element.children获取当前元素的子元素<div id="box1"> 我是box1 <span class="s1">我是s1</span> <span class="s1">我是s1</span> </div> <script> const box1 = document.getElementById("box1") const children = box1.children console.log(children.length) // 输出:2(2个span) </script>element.firstElementChild 获取当前元素的第一个子元素<p>Hello world! This is HTML5 Boilerplate.</p> <div id="box1"> 我是box1 <span class="s1">我是s1</span> <span class="s1">我是s1-2</span> </div> <h1>hello,world</h1> <script> const box1 = document.getElementById("box1") console.log(box1.firstElementChild) //输出: <span class="s1">我是s1</span> </script>element.lastElementChild 获取当前元素的最后一个子元素console.log(box1.lastElementChild) //输出: <span class="s1">我是s1-2</span>element.nextElementSibling 获取当前元素的下一个兄弟元素console.log(box1.nextElementSibling) //输出: <h1>hello,world</h1>element.previousElementSibling 获取当前元素的前一个兄弟元素console.log(box1.previousElementSibling) //输出: <p>Hello world! This is HTML5 Boilerplate.</p>element.parentNode 获取当前元素的父节点console.log(box1.parentNode) //输出: <body>...</body>element.tagName 获取当前元素的标签名console.log(box1.tagName) //输出: DIV>文本节点(Text)在DOM中,网页中所有的文本内容都是文本节点对象。可以通过元素来获取其中的文本节点对象,但是我们通常不会这么做。我们可以直接通过元素去修改其中的文本修改文本的三个属性element.textContent 获取或修改元素中的文本内容<div id="box1"> <span style="text-transform: uppercase;">我是box1</span> </div> <script> // 获取的是标签中的内容,不会考虑css样式 const box1 = document.getElementById("box1") box1.textContent = "新的内容" </script>element.innerText 获取或修改元素中的文本内容<script> // innerText获取内容时,会考虑css样式 // 通过innerText去读取CSS样式,会触发网页的重排(计算CSS样式) const box1 = document.getElementById("box1") box1.innerText = "新的内容" // 当字符串中有标签时,会自动对标签进行转义 box1.innerText = "<li>我是li</>" // <li> --> <li> </script>element.innerHTML 获取或修改元素中的html代码<script> // 可以直接向元素中添加html代码 const box1 = document.getElementById("box1") box1.innerHTML = "XXX" // innerHTML插入内容时,有被xss注入的风险 box1.innerHTML = "<、script src='https://sss/sss.js'><\/script>" </script>>属性节点(Attr)在DOM也是一个对象,通常不需要获取对象而是直接通过元素即可完成对其的各种操作。 如何操作属性节点:方式一读取:元素.属性名(class属性需要使用 className 来读取)读取一个布尔值时,会返回 true 或 false (如 disabled)修改:元素.属性名 = 属性名 <input disabled=“disabled” type="text" name="username" value="admin"> <script> const input = document.getElementsByName("username")[0] const input2 = document.querySelector("[name=username]") console.log(input) // console.log(input.type) input.name = "biu" // 修改:元素.属性名 = 属性名 </script>方式二读取:元素.getAttribute(属性名)修改:元素.setAttribute(属性名, 属性值)删除:元素.removeAttribute(属性名) <input disabled=“disabled” type="text" name="username" value="admin"> <script> const input = document.getElementsByName("username")[0] const input2 = document.querySelector("[name=username]") input.getAttribute("name") // 读取:元素.getAttribute(属性名) input.setAttribute("name","大王") // 修改:元素.setAttribute(属性名, 属性值) input.setAttribute("disabled",true) input.removeAttribute("disabled") // 删除:元素.removeAttribute(属性名) </script>>事件(Event)事件就是用户和页面之间发生的交互行为。例如:点击按钮、鼠标移动、双击按钮、敲击键盘、松开按键....可以通过为时间绑定响应函数(回调函数),来完成和用户之间的交互。绑定响应函数 直接在元素的属性中设置<button id="btn" onclick="alert('你点我干嘛~')">点我一下</button>为元素指定属性设置(回调函数)来绑定事件 (一个事件只能绑定一个响应函数)<script> // 获取到按钮对象 const btn = document.getElementById("btn") // 为按钮对象的事件属性设置响应函数 btn.onclick = function(){ alert("你点我干嘛~") } </script>通过元素 addEventListener( )方法来绑定事件 (可绑定多个,会依次执行)<script> // 通过元素 addEventListener( )方法来绑定事件 btn.addEventListener("click", function(){ alert("哈哈哈哈~") }) </script>>文档加载网页是自上向下加载的,如果将 js 的代码编写到网页的上边,在 js 代码执行时,网页还没有加载完毕,这时候会出现无法获取到 DOM 对象的情况。如何解决这个问题?将 script 标签编写到 body 的最后<body> <button id="btn">点我一下</button> <script> const btn = document.getElementById("btn") console.log(btn) </script> </body> 将代码编写到 window.onload 的回调函数中<body> <button id="btn">点我一下</button> <script> // window.onload 事件会在窗口中的内容加载完毕之后才触发 window.onload = function () { const btn = document.getElementById("btn") console.log(btn) } window.addEventListener("load", function () { const btn = document.getElementById("btn") alert(btn) }) </script> </body>将代码编写到 document 对象的 DOMContentLoaded 回调函数中<script> // document的DOMContentLoaded事件会在当前文档加载完毕之后触发 document.addEventListener("DOMContentLoaded", function () { const btn = document.getElementById("btn") alert(btn) }) </script>将代码编写到外部 js 文件,以 defer 形式引入<script defer src="./script/script.js"></script>>小练习