DOM

130 阅读9分钟

DOM的基本概念

DOM: 文档对象模型, 其实就是操作 html 中标签的一些能力
比如:
    获取一个元素(标签)
    移除一个元素
    创建一个元素
    向页面添加一个元素
    给元素绑定一个 事件
    获取元素的属性
    给元素添加一些 css 样式
    ......
 
DOM 的核心是 document 对象
    document 对象是 JS 内置的一个对象, 里面存储着专门用来操作元素的各种方法

DOM对象: 页面中的标签, 我们通过 JS 获取到以后, 就把这个对象叫做 DOM对象(DOM节点)

获取元素

1.获取非常规元素   非常规标签有(html,head,body)
     document.documentElement   -> 获取html标签
     例: console.log(document.documentElement)
     
     document.head              -> 获取head标签
     例: console.log(document.head)

     document.body              -> 获取body标签
     例: console.log(document.body)
     
2.获取常规元素
    2.1 通过 ID 名获取标签
        语法: document.getElementById('ID名')
        例: var box = document.getElementById('box')
            console.log(box)
            
    2.2 通过 class 名获取标签
        语法:document.getElementsByClassName('class名')
        注意: 因为在页面中可能会有多个元素的 class 相同,所以获取到的是一组元素,
              获取到后会把元素放在一个长得很像数组一样的  数据结构内, 但他并不是数组,我们称之为  伪数组
              伪数组:长得很像数组, 也是通过索引排序, 但是没有数组的方法
        例: 获取到页面中 class 名为 box1 的标签
            var box1 = document.getElementsByClassName('box1')
            console.log(box1)
            console.log(box1[0])
            console.log(box1[1])
            console.log(box1[2])
        
    2.3 通过 标签名获取
        语法: document.getElementsByTagName('标签名')
        注意: 获取到的也是一个长得很像数组一样的数据结构(伪数组)
               想要准确的获取到标签元素,我们需要通过索引来帮助我们拿到
        例: 获取到页面中 标签名为 div 的标签
            var divs = document.getElementsByTagName('div')
            console.log(divs) //[div#box, div.box1, div.box1, div.box1, box: div#box]
            console.log(divs[0])
               
    2.4 按照选择器的形式来获取元素
        2.4.1  querySelector, 这个方法允许我们想写 css 的时候的选择器一样获取标签
            语法:document.querySelector('选择器')
            注意:这个方法只能获取到一个元素, 就是满足条件的第一个元素
            例: var box2 = document.querySelector('.box1')
                console.log(box2)  
                var box3 = document.querySelector('div')
                console.log(box3)
            
        2.4.2  querySelectorAll, 该方法与 querySelector 选择器类似,只不过会将所有满足条件的元素都获取到, 也是放在一个伪数组内
                例: var box4 = document.querySelectorAll('.box1')
                    var box5 = document.querySelectorAll('div')
                    console.log(box4)//[div.box1, div.box1, div.box1]
                    console.log(box5)//[div#box, div.box1, div.box1, div.box1]
            

操作属性

我们获取到元素以后, 可以直接操作 DOM 的属性, 然后直接把效果展示在页面
    1.innerHTML
        获取元素内部的 HTML 结构
        我们也可以直接给这个属性重新赋值,达到修改页面的效果
        例:      var oDiv = document.querySelector('#box')
                 console.log(oDiv.innerHTML)
                 oDiv.innerHTML = '<p><span>各位, 早上好~~~这个文本是通过JS来设置的</span></p>'
        
    2.innerText
        获取元素内部得到文本(只能获取到文本, 获取不到 html 标签)
        我们也可以直接给这个属性重新复制,达到修改页面的效果
        例: var oDiv = document.querySelector('#box')
            oDiv.innerText = '<p><span>各位, 早上好~~~这个文本是通过JS来设置的</span></p>'
            

元素属性

1. 获取元素的某些属性
    语法:元素.getAttribute('要查询的属性名')
    返回值:查询到属性时返回对应的属性值, 没有查询到时 直接返回 null
    
2. 修改元素的某些属性
    语法:元素.setAttribute('对应的属性名', '对应的属性值')
    注意:如果元素没有对应的属性名, 那么相当于是新增的一个属性
    
3. 删除元素的某些属性
    语法:元素.removeAttribute('要删除的属性名')
    

h5 自定义属性

data-  表示该属性是一个自定义属性!!!!!!
data-  后边的内容才是属性名, 当前案例中属性名为a, 不是data-a
=      后边的内容是属性值
每一个   元素/DOM节点   天生自带一个属性, 叫做dataset, 是一个类似对象的数据结构
操作: 查询 增加 删除
    0.获取标签
         var oDiv = document.querySelector('div')
    1.访问元素的 dataset 属性    查询
         console.log(oDiv.dataset.a) //100
    2. 增加一个 h5 自定义属性
         oDiv.dataset.age = 18  // 标签中没有这个自定义属性, 所以是新增
         oDiv.dataset.a = 'QF666' //标签中有这个自定义属性, 相当于做了修改操作
    3. 删除
         delete oDiv.dataset.a
       

获取元素样式和类名

 获取元素样式
     语法:元素.style.某个属性
     注意:我们也可以给这个语法重新赋值, 达到修改元素样式的效果
     实例 操作:
         <div class="box"></div>
         0. 获取元素
                var oDiv = document.querySelector('.box')
         1. 获取元素样式 (只能获取行内样式)
                console.log(oDiv.style.weight)
                console.log(oDiv.style.height)
                // console.log(oDiv.style.background-color) 
                //直接这样写相当于写了一个 oDiv.style.background - color 是错误的   - 在JS中代表减法
                解决方法
                console.log(oDiv,style['background-color']) //中括号语法
                console.log(odiv.style.backgroundColor) //驼峰命名
         2.设置元素样式 (只能设置行内样式)
                oDiv.style.width = 666 + 'px'
                oDiv.style.background = 'red'
                
         3.获取 非行内样式 (也可以获取到行内样式)
                 语法:window.getComputedStyle(元素).要查询的 css 属性
                 注意:这种方式获取到的属性 是只读的(能获取到, 但不允许修改)!!!
                 console.log(window.getComputedStyle(oDiv).width)
                 console.log(window.getComputedStyle(oDiv).backgroundColor)
                 // window.getComputedStyle(oDiv).width = 800 + 'px' // 不允许修改 , 会有报错
          
          4. className  专门用来操作元素的 类名
                  语法:元素.className      我们也可以给他重新赋值,来达到修改元素的类名
                  例: oDiv.className = 'new_box'
                      console.log(oDiv.className)
          

获取 元素类名

1. className      专门用来操作元素的  类名
    语法:元素.className       我们也可以给他重新赋值,来达到修改元素的类名
2. classList
    新增 
        语法: 元素名.classList.add('新增元素名')
    删除
        语法: 元素名.classList.remove('元素名')
    

DOM 节点

 一般来说我们分为三个大类    
     元素节点(标签)
         通过 getElementBy... 获取到的都是元素节点
     文本节点(标签内的文字)
         通过 innerText 获取到的就是元素的文本节点
     属性节点(标签上的属性)
         通过 getAttribute 获取到的都是属性节点
         

获取子节点

1. 获取某一节点下 所有的 子一级 节点,       获取到的是一个 伪 数组
    语法: 元素.childNodes
    
2.获取某一节点下 所有的 子一节 元素节点    获取到的是一个 伪 数组
    语法: 元素.children
    
3. 获取某一节点下子一级的 第一个节点
    语法: 元素.firstChild
    
4. 获取某一节点下子一级的 最后一个节点
    语法: 元素.lastChild
    
5. 获取某一节点下子一级的 第一个元素节点
    语法: 元素.firstElementChild
    
6. 获取某一节点下子一级的 最后一个元素节点
    语法: 元素.lastElementChild
    
实例: <div>
        <p>你好</p>
        <span>测试文本</span>
        <h1> JS 是世界上最优美的语言</h1>
      </div>
      0. 获取元素
         var oDiv = document.querySelector('div')
      1. childNodes
         console.log(oDiv.childNodes)
         注: 拿到的是一个伪数组, 里边有 7 个节点
             [0]: text  从 <div> 一直到 <p> 中间有一个换行和一堆空格     这是一个文本节点
             [1]: p      这个就是 p 标签, 他是第二个节点, 这是一个 元素节点
             [2]: text   从 </p> 一直到 <span> 中间有一个换行和一堆空格  这是一个文本节点
             ......
       2. children
          console.log(oDiv.children)   这里只有 div 内部的标签
       3. firstChild
          console.log(oDiv.firstChild)     #text
       4. lastChild
           console.log(oDiv.lastChild)  #text
       5. firstElementChild
           console.log(oDiv.firstElementChild)
       6.lastElementChild
           console.log(oDiv.lastElementChild)
           

获取兄弟节点

var oSpan = document.querySelector('span')
1.获取对应的 下一个兄弟节点
    语法:元素.nextSibling
    例: console.log(oSpan.nextSibling) //#text
    
2. 获取对应的 上一兄弟节点
    语法:元素.previousSibling
    例: console.log(oSpan.previousSibling) //#text
     
3. 获取对应的 下一个兄弟元素节点
    语法:元素.nextElementSibling
    例: console.log(oSpan.nextElementSibling) //h1
    
4. 获取对应的 上一个兄弟元素节点
    语法:元素.previousElementSibling
    例: console.log(oSpan.previousElementSibling)  //p

获取父节点与属性节点

1. 父节点:
    语法:元素.parentNode
    
2. 获取元素的所有属性节点
    语法: 元素.attribute
    

节点属性

1.nodeType   节点属性
    节点中的一个属性  nodeType  能够区分当前节点是什么类型
          元素节点 返回 1
          属性节点 返回 2
          文本节点 返回 3
          
2.nodeName    节点名称
    元素节点  ->  大写的标签名   (LI / UL / DIV)
    属性节点  ->  text   (属性名)
    文本节点  ->  #text
    
3. nodeValue   节点的值
    元素节点  ->  没有 nodeValue 也就会输出 null
    属性节点  ->  对应的属性值
    文本节点  ->  对应的文本内容
        
    实例:<ul text="我是 UL 的一个属性">
            <li>holle</li>
          </ul>
          0. 获取元素
            var oUl = document.querySelector('ul')
          1. 元素节点
            var eleNode = oUl.firstElementChild
          2.属性节点
            var attrNode = oUl.attributes[0]
          3.文本节点(换行和空格)
            var textNode = oUl.firstChild
          nodeType
            console.log('元素节点:', eleNode.nodeType)  //1
            console.log('属性节点:', attrNode.nodeType)  //2
            console.log('文本节点:', textNode.nodeType)  //3
          nodeName
            console.log('元素节点:', eleNode.nodeName)  //LI
            console.log('属性节点:', attrNode.nodeName) //text
            console.log('文本节点:', textNode.nodeName) //#text
          nodeValue
            console.log('元素节点:', eleNode.nodeValue)  //null
            console.log('属性节点:', attrNode.nodeValue) //我是 UL 的一个属性
            console.log('文本节点:', textNode.nodeValue)

操作 DOM 节点

常规意义上的‘增删改查’ (在页面上增加一个节点, 首先,你应该先有一个节点)
    1.在 JS 中创建 一个节点
        语法: document.createElement('要创建的标签名')
        创建一个文本节点 (仅做了解)   语法:document.createTextNode
        
    2.向页面增加一个节点
        语法1: 元素.appendChild(要添加的节点)
            作用: 向元素的末尾追加一个节点
        
        语法2: 元素.insertBefore(要插入的节点, 插入到哪个节点的前面)
           注: 两个参数是必填项
               第二个参数传递正常节点时, 代表插入到这个节点的前面
               第二个节点传递的是 null时, 表示插入带 元素 到的末尾
        
    3.删除页面得到某一个节点
        语法1: 父节点.removeChild(要删除的节点)
        
        语法2: 节点.remove()
            作用:把当前节点删除
            
    4.修改页面的某一个节点
         语法: 父节点.replaceChild(新节点, 旧节点/要被修改的节点)
             作用: 将页面中的某一个节点 做一个替换
     
    5.获取页面的某一个节点
          之前获取 元素 的方法
          
    6.克隆一个节点(把一个节点复制出一个一模一样的)
         语法: 节点.cloneNode(参数)
             参数:默认是 false ,表示不克隆后代节点(只克隆标签不克隆其中的文本节点)
                 选填 true, 表示克隆后代节点
实例:
            <div class="box">
                <p>我是通过 HTML 手写的第一个文本节点</p>
                <p>我是通过 HTML 手写的第二个文本节点</p>
            </div>
            <script>
                let myDiv = document.querySelector('.box')
                let oP = document.querySelector('p')
                
                创建一个元素节点
                let oDiv = document.createElement('div')
                let oSpan = document.createElement('span')
                
                创建一个文本节点
                let oText = document.createTextNode('我是通过 JS 创建出来的文本节点')
                
                将刚创建的文本节点添加到元素节点中
                oDiv.appendChild(oText)
                
                向页面中添加一个节点
                myDiv.appendChild(oDiv1)
                myDiv.appendChild(oSpan1)
                (将我们通过 JS 创建的 div 标签,插入到页面的 p 标签的前面)
                myDiv.insertBefore(oDIv, oP)
                myDiv.insertBefore(oSpan)
                
                删除页面中 p 标签
                myDiv.removeChild(oP)
                
                修改页面中的 P 标签(用span 标签替换 p 标签)
                myDiv.replaceChild(sPan, oP)
                
                克隆 oP 节点 
                let cloneP = oP.cloneNode()  //不包含后代节点
                let cloneP = oP.cloneNode(true) // 克隆出一个和oP 这个节点 一模一样的 新节点 (包含后代节点)
            </script>

获取元素偏移量

 获取元素在页面上相对 参考父级 的 左边 和 上边 的距离
 参考父级:
         其实就是假设你要给一个元素 ‘绝对定位’,他是根据谁来进行定位,那么这个元素的偏移量参考父级就是谁
  获取元素的相对父级
      语法: 元素.offsetParent
  获取元素距离左边的距离
      语法: 元素.offsetLeft
  获取元素距离上边的距离
      语法: 元素.offsetTop
      

获取元素尺寸(元素的占地面积)

 语法1:  元素.offsetWidth
         元素.offsetHeight
 语法2:  元素.clientWidth
         元素.clientHeight
 区别:
     offset  -> 实际的宽度 / 高度 + padding + border
     client  -> 实际的宽度 / 高度 + padding