Web API—DOM(二)

本文详细介绍了DOM节点操作,包括节点属性、父子节点、兄弟节点以及节点操作方法。同时,讲解了DOM事件操作,如addEventListener、事件流三阶段、事件对象以及事件委托的应用。通过实例展示了如何动态创建列表、表格,以及处理事件监听和解除。此外,还探讨了offset和client系列属性在处理元素位置和大小时的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DOM-Web API

DOM节点操作

在这里插入图片描述

节点属性
 var box = document.getElementById("box");
 // 元素节点
 console.dir(box); 
 //nodeName: "DIV", nodeType: 1, nodeValue: null
 // 属性节点获取
 var idnode = box.getAttributeNode("id");
 console.dir(idnode); 
 //nodeName: "id", nodeType: 2, nodeValue: "box"
 idnode.nodeValue = "demo";
// 文本节点
 var childnodes = box.childNodes;
 console.log(childnodes); 
 //nodeName: "#text", nodeType: 3, nodeValue: "div 1"
 childnodes[0].nodeValue = "child 1"; //得到的下标是0
  • nodeType节点的类型
    • 属性值是数字,表示不同的节点类型共12种,只读
    • 1元素节点 2属性节点 3文本节点
  • nodeName节点的名称(只读)
  • nodeValue节点值
    • 返回或设置当前节点的值,元素节点的value始终是null
父子节点
  • childNodes

    只读属性,获取一个节点所有子节点的实时集合,动态变化

  • childeren

    只读,返回一个节点所有的子元素节点结合,动态更新

  • firstChild

    只读,返回该节点的第一个子节点,没有则返回null

  • lastChild

    只读,返回该节点的最后一个子节点,没有返回null

  • parentNode

    返回一个当前节点的父节点

  • parentElement

    返回一个当前节点的父元素节点

var box = document.getElementById("box");
        console.log(box.childNodes); //NodeList(5) [text, p, text, span, text]获取所有类型的子节点,其中text中保存的是换行
        console.log(box.children); //HTMLCollection(2) [p, span]获取所有元素类型的子节点
        console.log(box.firstChild); //#text所有类型的第一个
        console.log(box.lastElementChild); //<span>span小盒子</span>所有元素类型的最后一个
        console.log(box.parentNode); //<body>……</body>
        console.log(box.parentElement); //<body>……</body>
兄弟节点
  • nextSibling

    只读,返回与该节点同级的下一个节点,无则返null

  • previousSibling

    只读,返回与该节点同级的上一个节点,无则返null

  • nextElementSibling

    返回的是下/上一个元素节点(IE9以后才兼容)

  • previousElementSibling

var p3 = my$("p3");
        console.log(p3.nextSibling); //#text
        console.log(p3.nextElementSibling); // <p>这是段落4</p>
        console.log(p3.previousSibling); //#text
        console.log(p3.previousElementSibling); // <p>这是段落2</p>
节点操作
  • 创建节点

    • document.createElement(“div”)创建元素节点

    • document.createAttribute(“id”)创建属性节点

    • document.createTextNode(“hello”)创建文本节点

    • 一般将创建的新节点保存在变量中方便使用,创建的新的节点,是存储在内存中的,并没有添加到DOM树上

      //创建一个元素节点
      var div = document.createElement("div");
              console.dir(div); //nodeValue=1
      var id = document.createAttribute("class");
              console.dir(id); //nodeValue=2
      var txt = document.createTextNode("hello");
              console.dir(txt); //nodeValue=3
      
  • 添加节点

    • parentNode.appendChild(child);将一个节点添加到指定父节点的子节点列表末尾

      var p3 = my$("p3");
              box.appendChild(div);
      //文本节点也可以添加到元素内部
              div.appendChild(txt); 
      //自己创建的元素节点本身就是一个对象, 可以去添加一些新的属性和方法,这些操作将来在元素加载到DOM树中时,依旧保留
              box.appendChild(p3);
      //DOM中将原有节点也可以使用appendChild属性,执行的操作是剪贴,从原本位置删除,添加到最后,是因为在内存中这个原有节点只有一个,渲染时只能有一个位置
      
  • 替换、插入、删除节点

    • parentNode.replaceChild(newchild,oldchild);用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点

      // 替换节点 box.replaceChild(div, p3);
      
    • parentNode.insertBefore(newNode,referenceNode);在参考节点之前插入一个拥有指定父节点的子节点

      // 固定插入节点 box.insertBefore(div, p3);
      
    • parentNode.removeChild(child);移除当前节点的一个子节点,这个子节点必须存在于当前节点中

       // 移除节点 box.removeChild(p3);
      
  • 克隆节点

    • Node.cloneNode()克隆一个节点,并且可以选择是否克隆这个节点下的所有内容,参数是布尔值,表示是是否采用深度克隆

    • true则该节点的所有后代节点都会被克隆,false则只克隆该节点本身

    • 克隆时,标签上的属性和属性值也会被复制,写在标签行内的绑定事件可以被复制,但是通过JS动态绑定的事件不会被复制

       // 克隆元素
              var newbox = box.cloneNode(false);
              //浅克隆就只有这个节点
              var newbox = box.cloneNode(true); 
              //深克隆包括所有的内容
              document.body.appendChild(newbox);
              //添加到body的末尾
      
  • 节点的判断方法

    • Node.hasChildNodes():没有参数,返回一个Boolean布尔值,来表示该元素是否包含有子节点

    • Node.contains(child);返回一个Boolean布尔值,来表示传入的节点是否为该节点的后代节点

      // 判断是否有子节点
       console.log(box.hasChildNodes()); //true
       console.log(demo.hasChildNodes()); //false
      // 判断P3是否是box的子节点
       console.log(box.contains(p3)); //true
      
    • 判断是否有子节点方法总结

      • node.firstChild!==null

      • node.childNodes.length>0

      • node.hasChildNodes()

      • 如果是元素节点是否存在则使用box.children.length

案例分析
  • 动态创建列表

    • 三部曲,创建,添加,增内容

    • 如果有多条属性,那么就通过数组长度进行添加

      // 创建每一个ul里面的li数据
      for (var i = 0; i < names.length; i++) {
       var li = document.createElement("li");
       // 将li添加到ul中去
       ul.appendChild(li);
       // 并且要给每一个li标签给值
       li.innerHTML = names[i];
      }
      
  • 动态创建表格

    • 当有多个值,我们就可以使用对象,通过属性和属性值进行内容的增加

    • a标签通过元素节点添加后,需要我们自己设定一些属性,a.href=”JavaScript:void(0)“就可以实现点击不跳转

    • 点击删除,就需要我们对其添加点击事件,点击即删除

      for (var k in data) {
      // 创建一个td
        var td = document.createElement("td");
      // 将创建的td增加到tr中去
        tr.appendChild(td);
      // 需要给td里面塞入内容
        td.innerHTML = data[k];
        }
      // 除了前面动态获取的td外还要增加一个删除的td
        td = document.createElement("td");
      // 添加到tr中去
        tr.appendChild(td);
      // 最后一个td中的内容是a标签,老步骤,创建添加增内容
        var a = document.createElement("a");
        td.appendChild(a);
        a.innerHTML = "删除";
      // 增加href属性,要让它不进行跳转则返回0
        a.href = "javascript:void(0);"
      // 给每个a生成添加一个点击事件,一处所在的行
        a.onclick = function() {
      // 通过a的父级找到td,再通过td的父级找到tr
      tb.removeChild(this.parentNode.parentNode);
      }
      
  • 选择水果

    • children中的元素都是动态添加的,所有存在length值会不断的发生变化,所以我们应该给一个初始值

    • 通过观察可以发现,每次移动的值下标都是index=0,所以我们就可以直接让每次移动的数都是0

       var n = opts.length;
       for (var i = 0; i < n; i++) {
       // 由于children获取到的opts都是动态变化的
       // 所以我们每次都从index=0去取
       all.appendChild(opts[0]);
       }
      
DOM事件操作
addEventListener
  • 二级事件的添加,调用的是方法

  • element.addEventListener()方法,第一个参数是事件函数的字符串(直接书写"click",不需要加on),第二个参数是事件函数

  • 同一个元素可以多次绑定世家监听,同一个事件类型可以注册多个事件函数

  • 不支持IE9以下的浏览器

     var btn = document.getElementById("btn");
     // 使用DOM二级的方法添加多个事件
     btn.addEventListener("click", function() {
     alert(1);
    });
     btn.addEventListener("click", function() {
     alert(2);
    });
    
attachEvent
  • 是一种方法,传入的第一个参数是事件类型的字符串(需要加on),第二个参数是事件函数

  • 只支持IE10及以下的浏览器,IE8以下可能会出现事件混乱的现象

    btn.attachEvent("onclick", function() {
                alert(1);
     });
    
注册事件兼容写法
  • 自定义一个注册事件函数

  • 参数:事件源、事件类型(不加on)、事件函数

  • 浏览器能力检测,将某个方法的调用作为if语句的判断条件,如果浏览器认识该方法返回true,否则返回false

  • IE9以上浏览器使用addEventListener方法,IE9以下浏览器使用attachEvent方法

     var btn = document.getElementById("btn");
     // 调用函数
     addEvent(btn, "click", function() {
                    alert(330);
     })
     // 自己制作一个兼容的绑定事件函数,参数(事件源,事件类型,事件函数)
     function addEvent(ele, type, fn) {
     // IE9以上浏览器使用addEventListener方法
     //IE9以下浏览器使用attachEvent方法
     if (ele.addEventListener) {
       ele.addEventListener(type, fn);
      } else if (ele.attachEvent) {
       ele.attachEvent("on" + type, fn);
      }
    }
    
解除事件
  • 0级事件解除,直接赋null值

     // DOM 0级事件解除绑定
     btn.onclick = null;
    
  • element.removeEventListener()方法

    • 第一个参数是事件类型字符串,第二个参数是事件函数引用名,没办法移除一个匿名函数,在注册事件的时候需要单独声明一个有函数名的事件函数
    • 同样兼容性问题,不支持IE9以下浏览器
    // 解除二级事件绑定
     btn.removeEventListener("click", fun1);
    
  • element.detachEvent()方法

    • 第一个参数是事件类型的字符串(需要添加on),第二个参数是事件函数
    • 同样不能移除匿名函数,需要注册事件时单独声明一个有函数名的事件函数
    • 只支持IE10及以下的浏览器
     btn.detachEvent("onclick", fun1);
    
  • 移除事件的兼容写法

    • 方法和添加事件的兼容性写法一致
     // 解除事件
     removeEvent(btn, "click", fun2);
     // 自己制作一个兼容的绑定事件函数,参数(事件源,事件类型,事件函数)
     function removeEvent(ele, type, fn) {
     // IE9以上浏览器使用addEventListener方法
     //IE9以下浏览器使用attachEvent方法
     if (ele.removeEventListener) {
       ele.removeEventListener(type, fn);
      } else if (ele.detachEvent) {
       ele.detachEvent("on" + type, fn);
      }
    }
    
DOM事件流
事件流三阶段

事件捕获、事件执行、事件冒泡

  • 冒泡是从最小的元素节点开始向上父级祖先级显示
  • 捕获是从祖先级元素开始向下一直到最小元素节点
  • 当捕获和冒泡同时存在时,先执行捕获,然后再执行冒泡,捕获到最小元素时,根据JS中书写的先后顺序来决定自身是先执行捕获还是先执行冒泡
  • 绑定事件最后还有一个参数(true or false),用来决定是捕获还是冒泡,只对addEventListener()有效
    在这里插入图片描述
冒泡应用

事件委托

  • 利用事件冒泡,将子级的公共事件委托给父级添加,在父级内部想办法找到真正触发事件的最底层的事件源

  • 借用事件函数内部的一个参数e,e是事件对象,只要触发事件,函数内部都可以得到一个事件对象,对象中存储了关于事件的一系列数据

  • e.target属性记录的即时真正触发事件的事件源

     var list = document.getElementById("list");
     var lis = list.children;
     // 给 ul 添加点击事件
     list.onclick = function (e) {
     // e.target 属性记录的就是真正触发事件的事件源
     // 排除其他
       for (var i = 0 ; i < lis.length ; i++) {
           lis[i].style.backgroundColor = "";
       }
     //单独设置自己的样式
        e.target.style.backgroundColor = "pink";
    };
    
事件对象
  • 只要触发事件,就会有一个对象,内部存储了与事件相关的数据

  • e在低版本浏览器中会有兼容问题,低版本浏览器使用的是window.event

  • 事件对象常用的属性

    • e.eventPhase查看事件触发时所处的阶段

    • e.target用于获取触发事件的元素

    • e.srcElement获取触发事件的元素

    • e.currentTarget获取绑定事件的事件源元素

    • e.type获取事件的类型

    • e.clientX/e.clientY所有浏览器都支持,鼠标距离浏览器左上角的距离

    • e.pageX/e.pageY ie8不支持,鼠标距离整个HTML页面左上顶点的距离

       box1.onclick = function(e) {
       // e指的是存储事件对象的参数,只要事件被触发,e就会自动接收数据
       // 兼容问题
                  e = e || window.event;
       // 事件触发时所处的阶段 1:表示捕获 2:目标阶段 3:冒泡阶段
                  console.log(e.eventPhase); //2
                  var target = e.target || e.srcElement;
                  console.log(target); //获取真正触发点击的事件
                  console.log(e.currentTarget); //box1返回的永远是绑定事件源的元素,和this中存储的内容是一样的
                  console.log(e.type); 
       //click返回获取事件的类型,更多时候可能时给同一个元素对象添加不同的事件类型,对应执行的事件函数内部的代码不同。可以将所有给一个元素绑定的事件的事件函数写在一个函数内,通过函数内部的e.type判断走不同的分支,这样可以避免添加多个函数,占用更多的内存
                  console.log(e.clientX); 
       //得到的是距离浏览器左上角来参考
                  console.log(e.pageX); 
       //得到的是距离我们HTML页面的距离,下拉滚动后的获取值仍旧保持不变
      }
      
  • 取消默认行为的方法

    • e.preventDefault()取消默认行为
    • e.returnValue取消默认行为,低版本浏览器使用
  • 阻止事件传播的方法

    • e.stopPropagation()阻止冒泡,标准方式
    • e.cancelBubble=true阻止冒泡,IE低版本
offset系列属性
  • offsetParent偏移参考父级,距离自己最近的有定位的父级,如果都没有定位则参考body(html)

  • offsetLeft/offsetTop偏移位置

  • offsetWidth/offsetHeight偏移大小,元素自身border以内的宽度(border+paddin g)

在这里插入图片描述

client系列属性
  • 客户端大小,只关注自己

  • clientLeft、clientTop、clientWidth、clientHeight

  • 一般如果我们不希望有边框的存在,那么就使用client

在这里插入图片描述

scroll系列属性
  • 关注的是自己,不关心外部的尺寸

  • scrollLeft/scrollTop盒子内部滚动出去的尺寸

  • scrollWidth/scrollHeight盒子内容的宽度和高度

在这里插入图片描述

拖拽案例

在这里插入图片描述

 // 给drop添加一个鼠标按下事件,在内部继续绑定一个鼠标移动事件
        drop.onmousedown = function(e) {
 // 兼容问题
        e = e || window.event;
// 在鼠标按下之后需要记住鼠标距离元素的上部和左部的位置
        var l = e.pageX - box.offsetLeft;
        var t = e.pageY - box.offsetTop;
// 增加鼠标移动事件
        drop.onmousemove = function(e) {
        e = e || window.event;
// 在鼠标移动过程中,将鼠标位置-鼠标距离本身的位置=距离HTML偏移的位置
        var newleft = e.pageX - l;
        var newtop = e.pageY - t;
// 将我们计算后的值赋给样式
        box.style.left = newleft + "px";
        box.style.top = newtop + "px";
    }
}
弹出层案例
  • 实际上就使用一个div半透明盒子盖住其他元素,再增加弹出的内容的权重,就可以实现其他内容点击无效
  • 绑定事件,对display样式属性值进行修改,block则展现,none则隐藏

下篇内容更精彩~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值