DOM

116 阅读7分钟

1. DOM 的基本概念

Document Object Model 文档对象模型
 DOM: 页面中的标签。 我们通过 JS 获取到以后, 就把这个对象叫做 DOM对象(DOM节点)。
 document:   文档流,页面,根节点,但不是元素(标签)。document对象是 JS 内置的一个对象, 里边存储着专门用来操作
 元素的各种方法
 html:   承载了所有标签的最大元素,根元素节点
 head:   专门承载当前页面中的说明标签,这里的内容一般不在页面中显示
 body:   专门承载当前页面中的显示标签,真实显示在页面中的内容
 

2. 获取元素

获取非常规元素

      - html标签: document.documentElement
      - head标签: document.head
      - body标签: document.body
      - title标签: document.title

获取常规元素

1. 根据 id 获取元素
        + 语法: document.getElementById('元素 id 名')
        + 返回值: 
          - 如果页面中有id对应的元素,那么就是这个元素
          - 如果页面中没有id对应的元素,那么就是null
          
         例如:
         <div id="box">div 标签</div>
         var box = document.getElementById('box')
2. 根据 类名 获取元素
        + 语法: document.getElementsByClassName('元素 class名')
        + 返回值: 一定是一个伪数组
          - 如果页面中有 类名 对应的元素,那么有多少获取多少,放到伪数组中
          - 如果页面中没有 类名 对应的元素,那么就是空伪数组
          - 伪数组: 就是和数组一样都有length属性和索引的数据,但是没有数组的方法  
          
          例如:
            <div class="box_cla">我是 class 为 box_cla 的 div 标签1</div>
            <div class="box_cla">我是 class 为 box_cla 的 div 标签2</div>
            <div class="box_cla">我是 class 为 box_cla 的 div 标签3</div>
            
            var box_cla = document.getElementsByClassName('box_cla')
            console.log(box_cla[0])
            console.log(document.getElementsByClassName('box_cla')[1])
            console.log(box_cla[2])
          
3. 根据 标签名 获取元素
        + 语法: document.getElementsByTagName('标签名')
        + 返回值: 一定是一个伪数组
          - 如果页面中有 标签名 对应的元素,那么有多少获取多少,放到伪数组中
          - 如果页面中没有 标签名 对应的元素,那么就是空伪数组
          例如:
          document.getElementsByClassName('span');
4. 根据 选择器 获取一个标签
        + 语法: document.querySelector('选择器')
        + 返回值:
          - 如果页面中有 选择器 对应的元素,那么就返回对应的第一个元素(就是满足条件的第一个元素)
          - 如果页面中没有 选择器 对应的元素,那么就是null
            var el = document.querySelector('.box');
            var el2 = document.querySelector('#div');
5. 根据 选择器 获取一组标签
        @注意: 但是通过document.querySelectorAll 获取的伪数组可以调用forEach方法
        + 语法: document.querySelectorAll('选择器')
        + 返回值: 一定是一个伪数组
          - 如果页面中有 选择器 对应的元素,那么有多少获取多少,放到伪数组中
          - 如果页面中没有 选择器 对应的元素,那么就是空伪数组
          
        例如:
          var els = document.querySelectorAll('.box');
          els.forEach(function(value,key,arr){ 
            console.log(value,key,arr )
          })
          

3. 操作元素

1)操作元素属性

案例:HTML结构
  <div id="box" index='666' data-index='888' data-id=999>hello</div>
  <img src="https://img1.baidu.com/"> <br>
1. 操作原生属性
    原生属性
    - 在 W3C 规范中有的属性名
    - 比如: id class style type src href...     
    + 语法: 元素.属性名 = 属性值
    例如:
        获取: document.getElementById('box').id
        设置: document.querySelector('img').src = './01-操作元素的属性.html';
2. 操作自定义属性(非H5)
   自定义属性
   - 在 W3C 规范中没有的属性名,是我们自己在书写在标签上的 
   + 获取
        - 语法: 元素.getAttribute(属性名)
        + 返回值: 该元素自定义属性的值
        var res = document.getElementById('box').getAttribute('index');
        
    +增加
            自己在标签上添加 
            <div index='666'>hello</div>
            
    + 修改:
        - 语法: 元素.setAttribute(属性名,属性值)
        document.getElementById('box').setAttribute('stock',99);
        
    + 删除
        - 语法: 元素.removeAttribute(属性名)
        document.getElementById('box').removeAttribute('index')
3. 操作H5自定义属性
    H5自定义属性
    - 定义:每一个 元素节点 身上都有一个自带的属性名叫做 dataset。dataset属性的值是一个类似于对象
    的数据结构,存储的该标签上所有的H5自定义属性
    - 目的: 就是为了区分自定义属性和原生属性写在标签上的形式
    - 要求: 书写 H5 自定义属性的时候,都要 data- 开头  
    - 比如: data-index = '888'
      data- 表示这是 H5 自定义属性
      index 表示属性名
      '888' 表示属性值
      

    对于 H5 自定义属性的操作
    + 获取
      - 语法: 元素.dataset.属性名
      console.log( dv.dataset.size )
    + 增加
      - 语法: 元素.dataset.属性名 = 属性值
      dv.dataset.size = 999;
    + 修改
      - 语法: 元素.dataset.属性名 = 属性值
      dv.dataset.id = 777
    + 删除
      - 语法: delete 元素.dataset.属性名
      delete dv.dataset.index;

2)操作元素样式

例如:  
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Leon</title>
      <style>div{ height: 200px; }</style>
      <link rel="stylesheet" href="./test.css"> //test.css里设置 font-sizes 属性
    </head>
    <body>
      <div style="width: 100px;color: red;background-color: green;">hello</div>
    </body>
    </html>
    
    <script> var ele = document.getElementsByTagName('div')[0]; </script>
1. 获取元素行内样式
   语法: 元素.style.样式名  (只能获取元素的行内样式)  
   console.log( ele.style.width );// 100px
   console.log( ele.style.height );// 非行内样式
   console.log( ele.style.backgroundColor ) // 驼峰命名 输出green 
   console.log( ele.style['background-color'] ) // green
2. 获取元素的非行内样式
   语法: window.getComputedStyle(元素).样式名
   (能获取行内样式和非行内样式  这种方式获取到的属性 是只读的 不允许修改)
   
   在主流浏览器中不能使用
   console.log( window.getComputedStyle(ele).width )//100px 能获取行内样式
   console.log( window.getComputedStyle(ele).height )//200px 能获取行内样式
   console.log( window.getComputedStyle(ele).fontSize )//驼峰命名 输出20px
   console.log( window.getComputedStyle(ele)['font-size'] ) // 20px

   在低版本ie中获取元素的非行内样式(不能使用getComputedStyle)
   语法: 元素.currentStyle.样式名  
   console.log( ele.currentStyle.fontSize ) // 20px
   console.log( ele.currentStyle.width ) // 100px
   
  
封装一个获取元素样式的函数
       function getStyle(ele,style) {
         // 通过压力测试来判断浏览器是否可以
         // console.log( window.getComputedStyle )
         if(window.getComputedStyle){
           return window.getComputedStyle(ele)[style]
         }else{
           return ele.currentStyle[style]
         }
       }
       console.log( getStyle(ele,'width') );
3. 设置元素的样式
    语法: 元素.style.样式名 = 样式值
    ele.style.backgroundColor = 'blue';
    ele.style['background-color'] = 'blue';
    ele.style.fontSize = '50px';
    ele.style.width = 666 + 'px'
          

3)操作元素的类名

1. 元素.className
返回值:多个类名一起的字符串
获取: 元素.className
console.log( ele.className ) // 'class1 class2 class3'

设置: 元素.className = "值"
因为是用的是 = 赋值,会把之前的类名覆盖
ele.className = 'box';
ele.className = '';

追加类名 元素.className += ' 值'
ele.className += ' box'
2. 元素.classList
     每一个元素身上都有一个属性 叫做classList
     该属性对应的值是一个类似于 数组的解构,方法是该元素的所有类名
     增删改查都是对象元素的classList操作,有专门的方法
     + 增: 元素.classList.add(类名)     ele.classList.add('active');
     
     + 删: 元素.classList.remove(类名)  ele.classList.remove('b');
     
     + 切换: 元素.classList.toggle(类名)
       - 原来有该类名则删除,没有则添加
       

4)操作元素的内容

案例:
<body>
  <div> 你好 <p>hello world</p> 世界 </div>
  <input type="text" value="666">
</body>
1. 元素.innerHTML
语法: 元素.innerHTML
作用:获取元素 里面的的 HTML 结构
返回值类型:字符串
目的:我们也可以直接给这个属性重新赋值, 达到修改页面的效果
        <div class="content router-view">
            <div>哈哈哈哈 </div> 
        </div>
     console.log(document.querySelector('.router-view').innerHTML)
   //输出字符串 '<div>哈哈哈哈 </div>'
2. 元素.innerText
语法: 元素.innerText
作用: 获取元素内部的文本内容
返回值:获取元素内部的文本 (只能获取到文本, 获取不到 html 标签)

document.querySelector('div').innerText = '666';
document.querySelector('div').innerText = '<h1>888</h1>'
//页面输出 <h1>888</h1> 没有办法识别解析 html格式的字符串 
3. 表单元素.value
    - 表单标签的内容操作
    - 一个读写属性,其实就是原生属性value操作
    -      + 语法: 表单元素.value
      + 得到: 该表单元素的value值
    -      + 语法: 表单元素.vlaue = '值'
      + 作用: 设置表单元素的value值
      
      document.querySelector('input').value = 888 //input里的666被改为888

5)获取元素的尺寸

1.元素.offsetWdith/offsetHeight
    - 元素.offsetWdith
      + 获取元素的 内容+padding+border 区域的宽度
    - 元素.offsetHeight
      + 获取元素的 内容+padding+border 区域的高度
    - 注意: 不管盒子是什么模型,区域不变
    
2.元素.clientWdith/clientHeight
    - 元素.clientWdith
      + 获取元素的 内容+padding 区域的宽度
    - 元素.clientHeight
      + 获取元素的 内容+padding 区域的高度

6)获取元素的偏移量

1. 获取偏移量参考元素
    + 语法: 元素.offsetParent
    + 得到: 该元素的偏移量参考父级
      - 就是该元素的定位父级
      - 如果到body都没有定位父级,那么这里的offsetParent就是body
2. 元素.offsetLeft/offsetTop
    + 语法: 
      - 元素.offsetLeft
        + 获取元素相对于 offsetParent 的左侧距离
      - 元素.offsetTop
        + 获取元素相对于 offsetParent 的上方距离
3. 元素.clientLeft/clientTop
    + 语法: 
      - 元素.clientLeft
        + 获取元素(内容+padding区域) 相对于该元素border左边的尺寸
      - 元素.clientTop
        + 获取元素(内容+padding区域) 相对于该元素border上边的尺寸  

7)获取可视窗口尺寸

          + DOM 级别获取: 不包含滚动条
            - document.documentElement.clientHeight
            - document.documentElement.clientWidth
    
    注意: + BOM 级别获取: 包含滚动条
            - window.innerWidth
            - window.innerHeight