JS DOM相关

124 阅读11分钟

DOM的基本概念

DOM: 文档对象模型
         其实就是操作html 中标签的一些能力
         比如: 获取一个元素
                移除一个元素
                创建一个元素
                向页面添加一个元素
                给元素绑定一些事件
                获取元素的属性
                给元素添加一些css样式
                ...

DOM的核心就是 document 对象

document 对象就是 JS内置的一个对象, 里边存储着专门用来操作元素的各种方法

获取元素

获取非常规元素

       document.documentElement   ->  html标签
       document.head              ->  head标签
       document.body              ->  body标签
  //1.html 标签
   console.log(document.documentElement)

   //2. head标签
   console.log(document.head)

   //3. body标签
   console.log(document.body)

获取常规元素

       1. 通过  ID 名获取标签
         语法: document.getElementById('ID名')
       2. 通过 class 名获取标签
         语法: document.getElementByClassName('class名')   注意: Element有s  因为class名不唯一
                    因为页面中可能会有多个元素的class相同, 所以获取到的是一组元素
                    获取到后会把元素放在一个长得很像数组一样的  数据结构内,但他并不是数组, 我们管这种数据结构 叫做  伪数组
                    伪数组: 长得很像数组, 也是通过索引排列, 但是没有数组的方法
  
       3. 通过标签名获取
              语法: document.getElementsByTagName('标签名')
              注意: 获取到的也是一个长得很像数组一样的数据结构, 其实就是获取到了一个伪数组, 想要准确的获取到标签元素, 我们需要通过索引来帮助我们拿到
  
       4. 按照选择器的形式来获取元素
  
       4.1. querySelector,这个方法允许我们像写 css 的时候 的选择器一样获取标签
                          注意: 这个方法只能获取到一个元素, 就是满足条件的第一个元素
                          语法: document.querySelector('选择器')
  
       4.2. querySelectorAll, 该方法与querySelector 选择器类似, 只不过会将所有满足条件的元素都获取到, 也是放在一个伪数组
   //1 获取到页面中 ID名为box的标签
   var box = document.getElementById('box')   //获取到页面中 ID为box 的标签
   console.log(box)

  //2 获取到页面中 class名为box_cla的标签
  var box_cla = document.getElementsByClassName('box_cla')   //获取到页面中 class名为box_cla 的标签
    console.log(box_cla)
    console.log(box_cla[0]) 
    console.log(box_cla[1]) 
    console.log(box_cla[2])

   //直接打印和索引打印控制台效果不同
 
   //3 获取到页面中 标签名为div的标签
   var divs = document.getElementsByTagName('div')
   console.log(divs)//输出所有标签名为div的
   console.log(divs[0])//输出指定的

   //4.1  按照选择器的形式获取标签
   var box2 = document.querySelector('.box_cla')
   console.log(box2)
   var box3 = document.querySelector('div')
   console.log(box3) 

   //4.2 
   var box4 = document.querySelectorAll('.box_cla')
   console.log(box4)
   var box5 = document.querySelectorAll('div')
   console.log(box5) 

操作DOM属性

我们获取到元素以后,可以直接操作DOM的属性, 然后直接展示在页面

1. innerHTML
        获取元素内部的HTML结构
        我们也可以直接给这个属性重新赋值, 达到修改页面的效果
2. innerText
        获取到元素内部的文本(只能获取文本,不能获取HTML标签)
   var oDiv = document.querySelector('#box')
   console.log(oDiv)
   console.log(oDiv.innerHTML)  //<p><span>大家早上好!!!</span></p>
   oDiv.innerHTML = '<p><span>大家早上好!!!</span></p>' //  控制台不显示,但是页面显示文本
  
  
   console.log(oDiv.innerText)    //页面和控制台都显示  大家早上好!!!
   oDiv.innerText = '<p><span>大家早上好!!!</span></p>' 
   // 页面显示 <p><span>大家早上好!!!</span></p>

操作元素属性

获取元素的某些特性

  • 语法: 元素.getAttribute('要查询的属性名')
    
  • 返回值: 查询到 属性时返回对应的属性值, 没有查询到时 直接返回null
    

    修改(新增)元素的某些特性

  •  语法: 元素.setAttribute('对应的属性名', '对应的属性值')
    
  •  注意: 如果元素没有对应的属性名,那么相当于是新增的一个属性
    

    删除元素的某些特性

  • 语法:removeAttribute('要删除的属性名')
    
<div class="box" a="100"></div>
    // 0. 获取元素
    //var oDiv = document.querySelector('.box')
    var oDiv = document.getElementsByClassName('box')[0]//注意下标的写法
    // console.log(oDiv)
    
    //1. 获取
   console.log(oDiv.getAttribute('a'))
   console.log(oDiv.getAttribute('class'))
   console.log(oDiv.getAttribute('b'))  //null
   
   //2. 修改/新增
    oDiv.setAttribute('a', 'GX999')
    oDiv.setAttribute('class', 'bigbox')
    oDiv.setAttribute('b', 'qwer')
    console.log(oDiv.getAttribute('a'))
    
   //3. 删除
   oDiv.removeAttribute('a')
   oDiv.removeAttribute('class')

h5 自定义属性

data- 表示该属性是一个自定义属性
data- 后面的内容才是属性名, 当前案例中属性名为a, 不是data-a
 = 后的内容是属性值

每一个  元素/DOM节点  天生自带一个属性,叫做dataset,是一个类似对象的数据结构
 <div data-a="100"></div>
    // 0. 获取标签
    var oDiv = document.querySelector('div') 
    
    // 1. 访问元素的dataset 属性     =查询
    console.log(oDiv.dataset.a)  //100

    // 2.增加一个h5 自定义属性
    oDiv.dataset.age = 18  //新增
    console.log(oDiv.dataset.age) //18
    oDiv.dataset.a = 'gx666'  //修改

    // 3. 删除
    delete oDiv.dataset.a

元素样式

获取元素样式

语法: 元素.style.某个属性
注意: 
1. 我们也可以给这个语法重新赋值, 达到修改 元素样式的效果
2. 这种语法获取到的元素样式,只能获取到  行内样式
    // 0. 获取元素
        var oDiv = document.querySelector('.box')
    // 1. 获取元素样式
        //只能获取行内
        
        console.log(oDiv.style.width)
        console.log(oDiv.style.height)
        console.log(oDiv.style['background-color'])//中括号语法
        console.log(oDiv.style.backgroundColor)

    // 2. 设置元素样式
         //直接添加到行内
    oDiv.style.width = 666 + 'px'
    oDiv.style.backgroundColor = 'green'

获取非行内样式

语法:window.getComputedStyle(元素).要查询的css属性

 注意: 这种方式获取到的属性是只读的
      只读:能获取到,但是不允许修改
    console.log(window.getComputedStyle(oDiv).width)
    console.log(window.getComputedStyle(oDiv).backgroundColor)
  
   window.getComputedStyle(oDiv).width = 800 + 'px'  //不允许修改,会有报错

元素类名

获取元素类名

 1. className
    专门用来操作元素的类名
    语法: 元素.className
    我们也可以给他重新赋值, 来达到修改元素的类名,如果元素有多个类名,会全部删除变为新类名
    console.log(oDiv.className)
    oDiv.className = 'qwer'
 2. classList(更推荐)
    获取
    新增
    删除
    //2.1 获取
    console.log(oDiv.classList)

    //2.2 新增
    oDiv.classList.add('qwer')

    //2.3 删除
    oDiv.classList.remove('new_box')

DOM对象(节点node)

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

DOM节点分类

  • 一般来说我们分为三个大类 元素节点(标签) / 文本节点(标签内的文字) / 属性节点(标签 上 的属性)

      元素节点
         通过getElementBy... 获取到的都是元素节点(页面中的标签)
         
      属性节点
              通过getAttribute  获取到的是属性节点(与元素节点是父子关系)
              
      文本节点
              通过innerText 获取到的就是元素的文本节点(内容,空格,回车等)
    

获取子节点

  1. 获取某一节点下所有的 子一级 节点, 获取到的是一个伪数组
语法:元素.childNodes
  1. 获取某一节点下 所有的 子一级 元素节点, 获取到的是一个伪数组
语法:元素.children
  1. 获取某一节点下子一级的 第一个节点(不区分节点类型)
语法:元素.firstChild
  1. 获取某一节点下子一级的 最后一个节点(不区分节点类型)
语法:元素.lastChild
  1. 获取某一节点下子一级的 第一个元素节点
语法:元素.firstElementChild
  1. 获取某一节点下子一级的 最后一个元素节点
语法:元素.lastElementChild
  // 0.获取元素
    var oDiv = document.querySelector('div')

    // 1. childNodes
    console.log(oDiv.childNodes)
    NodeList(7) [text, p, text, span, text, h1, text]
    // 2.children
    console.log(oDiv.children)    // HTMLCollection(3) [p, span, h1],这里只有  div  内部的标签

    // 3.firstChild
    console.log(oDiv.firstChild)   //  #text

    // 4.lastChild
    console.log(oDiv.lastChild)   //  #text

    // 5.firstElementChild
    console.log(oDiv.firstElementChild)    //  <p>你好</p>

    // 6. lastElementChild
    console.log(oDiv.lastElementChild)     //  <h1>js是世界上最厉害的语言</h1>

获取兄弟节点

  1. 获取对应的 下一个兄弟节点

    语法:元素.nextSibling

  2. 获取对应的 上一个兄弟节点

    语法:元素.previousSibling

  3. 获取对应的 下一个兄弟元素节点

    语法:元素.nextElementSibling

  4. 获取对应的 上一个兄弟元素节点

    语法:元素.previousElementSibling

//0. 获取节点
   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>js是世界上最厉害的语言</h1>

//4. previousElementSibling
console.log(oSpan.previousElementSibling)   //<p>你好</p>

获取父节点与属性节点

  1. 父节点
  • 语法: 元素.parentNode
  1. 获取元素的所有属性节点
  • 语法: 元素.attributes
//0.获取节点
var oH = document.querySelector('h1')

//1. parentNode
console.log(oH.parentNode)

//2. attributes
console.log(oH.attributes)   //NamedNodeMap {0: id, 1: class, 2: test, 3: num, id: id, class: class, test: test, num: num, length: 4}

节点属性

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

  //2. nodeName
  console.log('元素节点: ', eleNode.nodeName)  // 元素节点:  LI
  console.log('属性节点: ', attrNode.nodeName) // 属性节点:  text
  console.log('文本节点: ', textNode.nodeName) // 文本节点:  #text

  //3. nodeValue
  console.log('元素节点: ', eleNode.nodeValue)   // 元素节点:  null
  console.log('属性节点: ', attrNode.nodeValue)  // 属性节点:  我是UL的一个属性
  console.log('文本节点: ', textNode.nodeValue)  // 文本节点:  

操纵 DOM 节点

常规意义上的操作 DOM 节点无非就是 增删改查(CRUD)

注意, 在增加节点前, 我们应该先有一个节点, 所以应该是

  1. 创建
  2. 向页面中增加一个节点
  3. 删除页面中的某一个节点
  4. 修改页面中的某一个节点
  5. 获取页面中的某一个节点
创建节点
  • createElement 创建一个元素节点
var oDiv = document.createElement('div')
console.log(oDiv)   // <div></div>
  • createTextNode 创建一个文本节点
var oDiv = document.createTextNode('我是一个文本节点~啦啦啦啦啦')
console.log(oDiv)   // 我是一个文本节点~啦啦啦啦啦
向页面中加入一个节点
  • appendChild: 向一个元素节点的末尾追加一个节点
    • 语法: 父节点.appendChild(要插入的子节点)
var oDiv = document.createElement('div')
var oText = document.createTextNode('我是一个文本节点~啦啦啦啦啦')

// 向 oDiv 中追加一个文本节点
oDiv.appendChild(oText)
console.log(oDiv)
  • insertBefore: 向一个元素节点前插入一个节点
    • 语法: 父节点.insertBefore(要插入的节点, 插入在哪一个节点的前面)
    • 注意点: insertBefore 的第二个参数不是可选项是必选项, 传递正常节点时代表:插入在哪一个节点的前面, 如果传递的是 null, 则表示插入到父节点的 末尾
<div>
    <p>我是一个 p 标签</p>
</div>
var oDiv = document.querySelector('div')
var oP = oDiv.querySelector('p')

// 创建一个元素节点
var oSpan = document.createElement('span')

// 将这个元素节点添加到 div 下的 p 的前面
oDiv.insertBefore(oSpan, oP)

console.log(oDiv)
/**
 *  <div>
 *      <span></span>
 *      <p>我是一个 p 标签</p>
 *  </div>
*/
删除页面中的某一个节点
  • removeChild: 移出某一节点下的某一个节点
    • 语法: 父节点.removeChild(要移除的子节点)
<div>
    <p>我是一个 p 标签</p>
</div>
var oDiv = document.querySelector('div')
var oP = oDiv.querySelector('p')

oDiv.removeChild(oP)
console.log(oDiv) // <div></div>
修改页面中的某一个节点
  • replaceChild: 将页面中的某一个节点替换掉
    • 语法: 父节点.replaceChild(新节点, 旧节点)
<div>
    <p>我是一个 p 标签</p>
</div>
var oDiv = document.querySelector('div')
var oP = oDiv.querySelector('p')
// 创建一个 span 节点
var oSpan = document.createElement('span')
// 向 span 元素中加点文字
oSpan.innerHTML = '我是新创建的 span 标签'

// 用创建的 span 标签替换原先 div 下的 p 标签
oDiv.replaceChild(oSpan, oP)

console.log(oDiv)
/*
    <div>
        <span>我是新创建的 span 标签</span>
    </div>
*/
克隆页面中的某一个节点
  • cloneNode: 把该节点复制一份一摸一样的
    • 语法: 节点.cloneNode(参数)
      • 默认是false, 表示不克隆后代节点
      • 选填是 true, 表示克隆后代节点
<div>
    <p>我是一个 p 标签</p>
</div>
var oDiv = document.querySelector('div')
var oP = oDiv.querySelector('p')

// 克隆节点
var cloneDiv = oDiv.cloneNode()
var cloneDiv1 = oDiv.cloneNode(true)
console.log(cloneDiv)
console.log(cloneDiv1)

获取元素的非行内样式

  • 操作 DOM 的时候 经常会操作元素的 CSS 样式, 所以我们免不了需要获取元素的样式
  • 元素.style.xxx 的方式也只能获取到元素的 行内样式
div {
    width: 100px;
}

<div style="height: 100px"></div>

var oDiv = document.querySelector('div')
console.log(oDiv.style.height)  // 100px
console.log(oDiv.style.width)  // ''
  • 所以我们要想获取元素的 非行内样式, 就需要使用 getComputedStyle 和 currentStyle
  • 这两个方法作用是一样的, 只不过一个是在 非 IE 浏览器, 一个在 IE 浏览器
getComputedStyle (非IE使用)
  • 语法: window.getComputedStyle(元素).要获取的属性
div {
    width: 100px;
}

<div style="height: 100px"></div>

var oDiv = document.querySelector('div')
console.log(window.getComputedSTYLE(oDiv).width)  // 100px
console.log(window.getComputedSTYLE(oDiv).height)  // 100px
currentStyle (IE使用)
  • 语法: 元素.currentStyle.要获取的属性
div {
    width: 100px;
}

<div style="height: 100px"></div>

var oDiv = document.querySelector('div')
console.log(oDiv.currentStyle.width)  // 100px
console.log(oDiv.currentStyle.height)  // 100px

获取元素偏移量

就是元素在页面上相对于参考父级的左边和上边的距离

offsetParent
  • 获取元素的偏移量参考父级
  • 其实就是假设你要给一个元素 绝对定位 的时候
  • 它是根据谁来进行定位的, 那么这个元素的偏移量参考父级就是谁
offsetLeft / offsetTop
  • 获取的事元素左边的偏移量和上边的偏移量
    • offsetLeft 该元素相对于参考父级的左侧偏移量
    • offsetTop 该元素相对于参考父级的上侧偏移量

获取元素尺寸

获取元素的占地面积

offsetWidth 和 offsetHeight
  • offsetWidth: 获取元素内容 + padding + border 的宽度
  • offsetHeight: 获取元素内容 + padding + border 的高度
clientWidth 和 clientHeight
  • clientWidth 获取元素内容 + padding 的宽度
  • clientHeight 获取元素内容 + padding 的高度
注意
  • 获取到的尺寸是没有单位的数字
  • 当元素在页面中不占位置的时候, 获取到的是 0
    • display: none 元素在页面不占位
    • visibility: hidden 元素在页面占位

获取浏览器窗口尺寸

可视区域的尺寸

  • document.documentElement.clientWidth: 浏览器可视窗口的宽度
  • document.documentElement.clientHeight: 浏览器可视窗口的高度