DOM编程

DOM编程

介绍

  • DOM编程是指使用JavaScript与HTML文档中的DOM(文档对象模型)进行交互的过程。

    • 文档:整个HTML网页文档
    • 对象:网页中的每一部分都转换为了对象
    • 模型:使用模型表示对象之间的关系
  • DOM是HTML文档的树状结构表示,它允许开发者使用JavaScript来访问、操作和修改HTML元素、属性和样式。

  • 通过DOM编程,开发者可以动态地创建、删除、修改和移动HTML元素,以及响应用户的交互事件。

  • 节点:Node--构成HTML文档最基本的单元

    • 常用节点:
      • 文档:整个HTML文档
      • 元素:HTML文档中的HTML标签
      • 属性:元素的属性
      • 文本:HTML中的文本内容(根据DOM标准,标签间的空白也算文本节点)

获取对象

  • document.getElementById() 可以通过id获取对象
<button id="btn">这是一个按钮</button>  
  
<script type="text/javascript">  
    //获取button对象  
    let  btn = document.getElementById("btn");  
    console.log(btn);  
    //修改按钮的文字  
    btn.innerHTML = "修改后的文字";  
  
</script>

事件

  • 事件是指在特定条件或用户操作发生时触发的动作或通知。
  • 事件可以是用户与程序交互的结果,例如点击按钮、输入文本、滚动页面等,也可以是程序内部的状态变化,例如定时器到期、数据加载完成等。
  • 在HTML中,可以通过使用事件属性事件监听器来处理事件。
    1. 事件属性:可以直接在HTML元素上使用事件属性来指定事件处理程序。
    • 常见的事件属性包括onclick(单击)、ondblclick(双击)、onmouseover、onkeydown等。
<button onclick="myFunction()">点击我</button>
<--点击后调用myFunction() -->

<button id="btn">点击我</button>
<script type="text/javascript">
//事件属性绑定回调函数
let btn = document.getElementById("btn");
btn.onclick = function(){
alert("你还真点了?");
}
</script>

2. 事件监听器:可以使用JavaScript代码来动态地添加事件监听器。通过这种方式,可以将事件处理程序与HTML元素分离,使代码更加清晰和可维护。常见的事件监听器方法包括addEventListenerattachEvent(用于旧版本的IE)。例如,要在按钮被点击时执行一个函数,可以使用addEventListener方法:

<button id="myButton">点击我</button>
<script type="text/javascript">
document.getElementById("myButton").addEventListener("click", myFunction);
</script>

文档加载

  • 浏览器从上到下加载页面
  • 将js代码写到下面就是为了先加载完页面在执行js代码
  • window.onload事件在整个页面加载完成后触发
<script type="text/javascript">  
  window.onload = function () {  
    let btnElt = document.getElementById("btn");  
    btnElt.onclick = function () {  
      let value = document.getElementById("username").value;  
      alert(value);  
    }  
  }  
</script>  
  
<input type="text" id="username">  
<input type="button" value="获取文本框的value" id="btn">  

DOM查询

通过document

  • 通过document对象调用获取元素节点
    • getElementById 通过id属性获取一个元素节点对象
    • getElementsByTagName 通过标签名获取一组元素节点对象
    • getElementsByName 通过name属性获取一组元素节点对象
    • querySelectorquerySelectorAll方法通过CSS选择器来获取元素节点。querySelector方法返回匹配选择器的第一个元素节点,而querySelectorAll方法返回匹配选择器的所有元素节点的对象集合。
    • 获取body标签: document.getElementsByTagName("body")[0]document.body
    • 获取html根标签:document.documentElement
    • 获取页面所有元素:document.alldocument.getElementsByTagName("*")
    • 通过class属性获取一组元素节点:document.getElementsByClassName("box")(IE8以下不兼容)或document.querySelector(".box")
  • 如果要读取元素节点的属性,直接使用 元素.属性名 即可。class属性除外,需要使用 元素.calssName
<div id="myDiv">这是一个div元素</div>
<script type="text/javascript">  
let element = document.getElementById("myDiv");
</script>  

<p>这是一个段落</p>
<p>这是另一个段落</p>
<script type="text/javascript">  
let elements = document.getElementsByTagName("p");
</script>  

<input type="text" name="myInput" value="value">
<script type="text/javascript">  
let elements = document.getElementsByName("myInput");
//如果要读取元素节点的属性,直接使用 元素.属性名 即可。class属性除外,需要使用 元素.calssName
alerrt(myInput[0].value);
</script>  

<div class="box1" id="#myDiv">
<div class="div1">这是一个div元素</div>
<div class="div2">这是另一个div元素</div>
</div>

<script type="text/javascript">  
//查找id为myDiv的元素下第一个div
let element = document.querySelector("#myDiv div");
//查找class为box1的元素下所有div
let elements = document.querySelectorAll(".box1 div");
</script>  
  • innrtHTML和innerText
    • innerHTML属性用于获取或设置元素的HTML内容。它返回一个字符串,包含元素的所有HTML标记和文本内容。通过设置innerHTML属性,可以动态地修改元素的内容,包括添加、删除或修改HTML标记和文本。
    • innerText属性用于获取或设置元素的纯文本内容,即不包含任何HTML标记。它返回一个字符串,只包含元素的文本内容,而不包括HTML标记。通过设置innerText属性,可以动态地修改元素的文本内容。
<div id="myDiv">Hello <strong>World</strong></div>
<script type="text/javascript"> 
let element = document.getElementById("myDiv");
console.log(element.innerHTML); 
// 输出:Hello <strong>World</strong>
element.innerHTML = "Goodbye";
</script>  

<div id="myDiv2">Hello <strong>World</strong></div>
<script type="text/javascript"> 
let element = document.getElementById("myDiv2");
console.log(element.innerText); 
// 输出:Hello World
element.innerText = "Goodbye";
</script>  

通过具体元素

  • 通过子节点
    • getElementsByTagName()方法,返回当前节点的指定标签名后代节点(与document.getElementsByTagName()获取页面所有节点相比,具体元素.getElementsByTagName()只获取具体元素节点下的节点)
    • childNodes 属性,表示当前节点的所有子节点,包括文本节点
    • children 属性,表示当前节点的所有子节点,不包括文本节点
    • firstChild属性,表示当前节点的第一个子节点,包括空白文本节点
    • firstElementChild属性,表示当前节点的第一个子元素,不包括空白文本节点。注意该属性IE8以下不兼容。
    • lastChild属性,表示当前节点的最后一个子节点,包括空白文本节点
<div id="myDiv">  
  <p id="p1">你居住的城市?</p>  
  <ul id="city">  
    <li id="bj">北京</li>  
    <li>上海</li>  
    <li>广州</li>  
  </ul>  <p>你使用的手机品牌?</p>  
  <ul id="phone">  
    <li id="mi">小米</li>  
    <li id="apple">苹果</li>  
    <li >三星</li>  
  </ul>  <button type="button" id="btn1">getElementsByTagName</button>  
  <button type="button" id="btn2">childNodes</button>  
  <button type="button" id="btn3">children</button>  
  <button type="button" id="btn4">firstChild</button>  
  <button type="button" id="btn5">lastChild</button>  
</div>
 window.onload = function () {  
// 通过具体元素节点调用  
  //1.getElementsByTagName()方法,返回当前节点的指定标签名后代节点  
      document.getElementById("btn1").addEventListener("click", function() {  
        let descendants = document.getElementById("city").getElementsByTagName("*");  
        alert("city的后代节点,包括空文本节点:" + descendants.length);  
      });  
  
      //2.childNodes 属性,表示当前节点的所有子节点,包括文本节点  
      document  .getElementById("btn2").addEventListener("click", function() {  
        let childNodes = document.getElementById("city").childNodes;  
        let count = 0;  
        for (let i = 0; i < childNodes.length; i++) {  
          if (childNodes[i].nodeType !== 3) {//nodeType==3是文本类型  
            count++;  
          }  
        }  
        alert("city的所有子节点的数量,不包括文本节点:" + count);  
      });  
      //3.children属性,表示当前节点的所有子节点,不包括文本节点  
      document.getElementById("btn3").addEventListener("click", function() {  
        let children = document.getElementById("phone").children;  
        alert("phone的所有子节点的数量,不包括文本节点:" + children.length);  
      });  
      //4.firstChild属性,表示当前节点的第一个子节点  
      document.getElementById("btn4").addEventListener("click", function() {  
        let firstChild = document.getElementById("phone").firstChild;  
        alert("phone的第一个子节点:" + firstChild.nodeName);  
      });  
  
      //5.lastChild属性,表示当前节点的最后一个子节点  
      document.getElementById("btn5").addEventListener("click", function() {  
        let lastChild = document.getElementById("phone").lastChild;  
        alert("phone的最后一个子节点:" + lastChild.nodeName);  
      });  
  
    }
ul {  
  display: flex;  
  list-style-type: none;  
}  
li {  
  margin-right: 10px;  
}
  • 通过父节点和兄弟节点
    • parentNode 属性,返回指定节点的父节点,无论父节点是什么类型(可以是元素节点、文本节点、注释节点等)。
    • parentElement 属性,返回指定元素节点的父元素节点。如果父节点不是元素节点,则返回null。
    • previousSibling 属性,获取当前节点的前一个兄弟节点,无论兄弟节点是什么类型(可以是元素节点、文本节点、注释节点等)。
    • previousElementSibling 属性,获取当前节点的前一个兄弟元素。IE8以下不支持
    • nextSibling 属性,获取当前节点的后一个兄弟节点,无论兄弟节点是什么类型(可以是元素节点、文本节点、注释节点等)。
    • nextElementSibling 属性,获取当前节点的后一个兄弟元素。IE8以下不支持。
<div id="myDiv">  
  <p id="p1">你居住的城市?</p>  
  <ul id="city">  
    <li id="bj">北京</li>  
    <li>上海</li>  
    <li>广州</li>  
  </ul>  <p>你使用的手机品牌?</p>  
  <ul id="phone">  
    <li id="Mi">小米</li>  
    <li id="Apple">苹果</li>  
    <li id="Samsung">三星</li>  
  </ul>  <button type="button" id="btn1">parentNode</button>  
  <button type="button" id="btn2">previousSibling</button>  
  <button type="button" id="btn3">nextSibling</button>  
  </div>
//定义一个函数,专门来指定元素单击响应函数  
function myClick(elmId,fun) {  
    let btn = document.getElementById(elmId);  
    btn.onclick = fun;  
}  
  
window.onload = function () {  
    //为id为bj的节点的父节点city,绑定单击响应函数  
    myClick("btn1",function () {  
        let bj = document.getElementById("bj");  
        // let bjPn = bj.parentNode;  
        let bjPn = bj.parentElement;  
        alert(bjPn.innerText);  
    })  
  
    //为id为Apple的前一个兄弟节点绑定单击相应函数  
    myClick("btn2",function () {  
        let apple = document.getElementById("Apple");  
        // let ps = apple.previousSibling;  
        let ps = apple.previousElementSibling;  
        alert(ps.innerText);  
    })  
  
    myClick("btn3",function () {  
        let apple = document.getElementById("Apple");  
        // let ns = apple.nextSibling;  
        let ns = apple.nextElementSibling;  
        alert(ns.innerText);  
    })  
}

DOM增删改

  1. 增加元素

    • createElement方法,创建新的HTML元素。需要一个标签名作为参数,会根据标签名创建节点对象
    • createTextNode方法,创建新的文本节点。需要一个文本作为参数。
    • appendChild方法,向父节点添加新的子节点。语法:父节点.appendChild(新子节点)
    • insertBefore方法,向指定子节点前面插入新的子节点。语法:父节点.insertBefore(新子节点,指定子节点)
    • repaceChild方法,替换子节点。语法:父节点.repaceChild(新子节点,旧子节点)
  2. 删除元素

    • removeChild方法,删除子节点。语法:父节点.repaceChild(子节点)
    • 可以使用指定子节点.parentNode.removeChild(指定子节点)来删除不知道父节点的子节点。该方法更常用。
  3. 修改元素

    • setAttribute方法,改变元素的属性。
    • innerHTML方法,也可以改变元素属性。此外,该方法也可以实现DOM的增删改,但是建议与前面的方法结合使用。
<div class="box1">  
  <ul id="city">  
    <p>你喜欢那个城市?</p>  
    <li id="bj">北京</li>  
    <li>上海</li>  
    <li id="dj">东京</li>  
    <li id="hsd">华盛顿</li>  
  </ul></div>  
<div class="box2">  
  <ul id="btn">  
    <li><button type="button" id="btn1">创建一个“广州”节点,添加到#city下</button> </li>  
    <li><button type="button" id="btn2">将“广州”节点插入到#bj前</button> </li>  
    <li><button type="button" id="btn3">使用“广州”节点替换#dj</button> </li>  
    <li><button type="button" id="btn4">删除#hsd节点</button> </li>  
    <li><button type="button" id="btn5">读取#city内的HTML代码</button> </li>  
  </ul></div>
//创建单击响应函数  
function myClick(btnId,fun) {  
    let btn = document.getElementById(btnId);  
    btn.onclick = fun;  
}  
  
window.onload = function () {  
    //创建一个“广州”节点,添加到#city下  
        //1. 为按钮绑定单击响应函数  
    myClick("btn1",function () {  
        //2.创建广州节点  
        let gz = document.createElement('li');  
        //3. 创建广州文本节点  
        let gzText = document.createTextNode("广州");  
        //4. 为广州节点绑定文本子节点  
        gz.appendChild(gzText);  
        //也可以直接修改gz节点的innerHTML或innerText  
        // gz.innerHTML = "广州";  
        //5. 为#city绑定广州子节点  
        let city = document.getElementById("city");  
        city.appendChild(gz);  
    })  
  
//    将“广州”节点插入到#bj前  
        //1. 为按钮绑定单击响应函数  
    myClick("btn2",function () {  
        //2.创建广州节点  
        let gz = document.createElement("li");  
        //3.设置gz的文本内容  
        gz.innerText = "广州";  
        //4. 获取#bj节点  
        let bj = document.getElementById("bj");  
        //5. 将gz插入在#bj前  
        bj.parentNode.insertBefore(gz,bj);  
    })  
  
// 使用“广州”节点替换#dj  
    myClick("btn3",function () {  
        //2.创建广州节点  
        let gz = document.createElement("li");  
        //3.设置gz的文本内容  
        gz.innerText = "广州";  
        //4. 获取#bj节点  
        let dj = document.getElementById("dj");  
        //5. 将gz替换#dj  
        dj.parentNode.replaceChild(gz,dj);  
    })  
  
// 删除#hsd节点  
    myClick("btn4",function () {  
        //获取#hsd节点  
        let hsd = document.getElementById("hsd");  
        //删除  
        hsd.parentNode.removeChild(hsd);  
    })  
    // 读取#city内的HTML代码  
    myClick("btn5",function () {  
        let city = document.getElementById("city");  
        alert(city.innerHTML);  
    })  
      
}

DOM操作CSS

读取和修改内联样式

  • 元素.style.样式名=样式值通过js修改元素内联样式,因为内联样式显示优先级较高,就覆盖了样式表中的样式。但是如果原样式有!important关键字则js修改样式无效,因此尽量不要为样式使用该关键字。
  • 如果css样式名中含有-,需要将该样式修改为驼峰命名法。例如background-color修改为backgroundColor
box1.style.width = "300px";//将box1的width修改为300px

box1.style.backgroundColor = "blue";//修改box1的颜色

alert(box1.style.width);//读取内联样式
  • 元素.style.样式名也可以读取元素的内联样式

读取和修改样式

  • getComputedStyle方法可以读取元素的当前样式
    • 语法getComputedStyle(要获取的元素,伪元素/null)
    • 该方法返回一个对象,封装了当前元素对应样式。
    • 可以通过对象.样式名获取样式,如果获取的样式没有设置,会返回一个真实值,如width不会返回auto,而是实际的值。IE8以下不支持。
  • 元素.currentStyle.样式名可以读取元素的当前样式,只有IE支持。
  • 以上方法/属性获取的样式都是只读的,要修改必须通过style属性
function getStyle(obj,name) {  
    //普通浏览器  
if (window.getComputedStyle){  //属性为找到返回undified
    return getComputedStyle(obj,null)[name];  
}else {  
    //IE8  
    return obj.currentStyle[name];  
}  
  
}
  • clientWidthclientHeight可以获取元素的可见宽度和高度,包括内容区和内边距,只读不可修改。
  • offsetWidthoffsetHeight 可以获取元素的整个宽度和高度,包括内容区和内边距和边框,只读不可修改。
  • offsetParent获取当前元素的开启了定位的祖先元素(默认为body)
  • offsetLeft获取当前元素相对于开启了定位的祖先元素的水平偏移量,offsetTop获取当前元素相对于开启了定位的祖先元素的垂直偏移量
  • scrollHeightscrollWidth获取当前元素整个滚动区域高度和宽度(谷歌浏览器认为浏览器的滚动条是body的,火狐等浏览器认为是html的)
  • scrollLeftscrollTop获取当前元素水平滚动条滚动的距离和宽度
  • 垂直滚动条滚动到底满足:scrollHeight - scrollTop == clientHeight。可应用于协议,只有当协议全部阅读完(滚动到底),才可以使用。推荐使用:parseInt(this.scrollHeight - this.scrollTop) == this.clientHeight,因为某些浏览器存在误差。
let box1 = document.getElementById('box1');
  console.log(box1.clientWidth);//获取可见宽度
  console.log(box1.offsetWidth);//获取全部宽度
  console.log(box1.offsetParent);//获取定位的祖先元素

练习

1 图片切换

  • 要求
    • 当点击按键时切换图片
    • 实现4张图片的循环切换
    • info显示共几张和当前是第几张图片
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>练习1-图片切换</title>  
  <style type="text/css">  
    *{  
      margin: 0;  
      padding: 0;  
    }  
  
    #outer{  
      width: 476px;  
      margin: 50px auto;  
      padding: 10px;  
      background-color: #bbffaa;  
      text-align: center;  
    }  
  
  </style>  
  
  <script type="text/javascript">  
    //要切换图片就是要修改img标签的src  
  //  可以使用数组保存图片的路径  
  //  使用变量保存当前索引  
  //点击按钮后,重新设置信息
  </script>  
</head>  
<body>  
<div id="outer">  
  <p id="info">一共 4 张图片,当前第  张</p>  
  <img src="img/bomb_0.png" alt="bomb1"/>  
  <button type="button" id="prev">上一张</button>  
  <button type="button" id="next">下一张</button>  
</div>  
</body>  
</html>

2 全选练习

  • 要求
    • 当点击全选,所有多选框都选择;当点击全不选,所有多选都不选
    • 当点击反选,选择之前选择的剩余未选择的
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>练习2 全选练习</title>  
  <style type="text/css">  
    input[type="checkbox"] {  
      display: inline-block;  
      margin-right: 10px;  
    }  
  </style>  
  <script type="text/javascript" src="../js/练习2-全选练习.js"></script>  
</head>  
<body>  
<form id="sport">  
  <p>你爱好的运动是?</p>  
  <input type="checkbox" name="sport" value="足球" id="football">足球  
  <input type="checkbox" name="sport" value="篮球" id="basketball">篮球  
  <input type="checkbox" name="sport" value="乒乓球" id="pingpong">乒乓球  
  <input type="checkbox" name="sport" value="羽毛球" >羽毛球<br>  
</form>  
<button type="button" id="btn1">全选</button>  
<button type="button" id="btn2">全不选</button>  
<button type="button" id="btn3">反选</button>  
<button type="button" id="btn4">提交</button>  
</body>  
</html>
  • 答案
//创建绑定函数  
function myClick(elemId,fun) {  
    let btn =  document.getElementById(elemId);  
    btn.onclick = fun;  
}  
window.onload = function () {  
    let elem1 = document.getElementById("football");  
    let elem3 = document.getElementById("pingpong");  
    let elem2 = elem3.previousElementSibling;  
    let elem4 = elem3.nextElementSibling;  
    // alert(elem2.innerHTML);  
    // alert(elem4.innerHTML);
    let elemArr = [elem1,elem2,elem3,elem4];  
  
//      全选  
    myClick("btn1",function () {  
        for (let i = 0; i < elemArr.length; i++) {  
            elemArr[i].checked = true;  
        }  
    })  
//    全不选  
    myClick("btn2",function () {  
        for (let i = 0; i < elemArr.length; i++) {  
            elemArr[i].checked = false;  
        }  
    })  
//    反选  
    myClick("btn3",function () {  
        for (let i = 0; i < elemArr.length; i++) {  
            if (elemArr[i].checked){  
                elemArr[i].checked = false;  
            }else {  
                elemArr[i].checked = true;  
            }  
        }  
    })  
}

3 表单的增删改

  • 要求:
    • 当点击Delete,提示是否真的删除。点击确定,删除,点击取消,不删除。
    • 在name、email、salary中填写内容,点击submit后,添加记录

4 霸王条款

  • 要求:
    • 只有当协议滚动到最底两个按钮才可以使用
    <style>
        h3{
            font-size: 20px;
        }
        #info{
            font-size: 14px;
            width: 300px;
            height: 500px;
            overflow: auto;
            background-color: #bfa;
        }
    </style>
    <script type="text/javascript" >
        window.onload = function(){
            let info = document.getElementById("info");
        info.onscroll = function(){
            if (this.scrollHeight - this.scrollTop == this.clientHeight) {
              //disabled属性可以设置禁用一个表单控件,
            //   如果为true, 则该表单控件被禁用,
            //   如果为false,则该表单控件可用
                inputs[0].disabled = false;
                inputs[1].disabled = false;
            }
        }
    }
    </script>
    <h3>用户注册</h3>
    <p id="info">
	省略很多字
    </p>
    <input type="checkbox" name="" id="read" disabled="disabled">我已同意以上协议</input>
    <input type="submit" name="" id="sub" disabled="disabled">同意协议并注册</input>
posted @ 2023-08-08 21:36  FL不凡  阅读(67)  评论(0编辑  收藏  举报