Javascript系列之dom操作以及client、scroll及offset整理

1,190 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

整理这篇dom操作的初衷,也就是希望自己的知识能够有个体系吧,点连成线,线成为面,笔者也只是极其普通的前端程序员,大佬不喜勿喷哈。

1.dom之盒模型属性:

DOM:docuemt object model 文档对象模型,提供系列的属性和方法,让我们能够在js中操作页面中的元素。

🚀获取元素的属性和方法:

//id获取元素
docuemnt.getElemnetById([id])

//通过标签名获取
[context].getElementByTagName([tagName])

//通过样式名获取(在ie6-8下不兼容)
getElementByClassName([class-name]) ;

//在ie浏览器中只对表单元素的name有作用
document.getElementByName([name]);

[context].querySelector([selector]);

[context].querySelectorAll([selector]);

//获取页面文档
document

//获取html
document.docuementElement

//获取head
document.head

//获取body
doucment.body

//获取所有子节点
childNodes

//获取所有元素子节点(ie6-8中获取注释集结点当做元素节点获取到)
children

//父节点
parentNode

(下面开始所有带element的,在ie6-8都不兼容)
//第一个子节点
firstChild / firstElementChild
//最后一个子节点
lastChild / lastElementChild
//上一个兄弟节点
previousSibling / previousElementSibling
//下一个兄弟节点
nextSibling  / nextElementSibling

🚀DOM的增删改操作:

document.createElement([tag-name])

document.createTextNode([content])

字符串拼接,然后基于innerHtml/innerText存放到容器中

[parent].appendChild([child])

[Parent].insertBefore([element],[newElement])

[element].cloneNode([true/false]) //深浅克隆

[parent].removeChild([element])

//设置自定义属性
[element].xxx = xxx;
//获取自定义属性
[element].xxx

//写在结构上的属性
[elemnet].setAttribute('attrKey',attrValue);
[element].getAttribute('attrKey);
[element].remveAttribute('attrKey);
                                    

获取元素样式和操作样式:

//修改行内样式
[element].style.xxx = xxx;

//设置样式类来修改样式
[element].className = xxx;

//获取的是当前元素写在行内的样式,如果有这个样式,但是没有写在行内上,则获取不到
let w = [element].style.width;

2.client相关:

let box = document.getElementById('box');
//获取盒子可视区域宽高(内容宽度 + 左右padding值或者上下padding值,注意不包含border哈😑)
box.clientWidth
box.clientHeight

//获取顶部边框宽度(没有下边框宽度)
box.clientTop
//获取左边边框宽度(没有右边框宽度)
box.clientLeft

😑这里需要注意的:

  • 如果内容溢出是不会对clientHeightclientWidth造成影响的
  • 通过clientWidthclientHeight获取到的是没有单位的数值
  • 获取的结果是整数,会四舍五入

获取html可视区的宽高:

  • 可视区宽:document.documentElement.clientWidth ||document.body.clientWidth

    • (document.body.clientWidth为兼容性处理)
  • 可视区高:docuemnt.docuemntElement.clientHeight || docuemnt.body.clientHeight

    • (同上)

那么如何让一个盒子水平和垂直方向都居中呢?🤔

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>client系列之居中处理</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    .box{
      width: 300px;
      height: 300px;
      border: 10px solid lightblue;
      background:lightcyan;
      padding: 20px;
      font-size: 18px;
      line-height: 35px;
    }
  </style>
</head>
<body>
  <div class="box" id="box">
    夫君子之行,静以修身,俭以养德,非淡泊无以明志,非宁静无以致远。夫学须静也,非学无以广才,非志无以成学。
  </div>
<script src="./js/index.js"></script>
</body>
</html>

方案①:定位

    .box{
      position: absolute;
      left: 50%;
      top: 50%;
      margin-left: -180px;
      margin-top: -180px;
    }

方案②:css3位移(不知道宽高的情况下,也能实现)

    .box{
      position: absolute;
      left: 50%;
      top: 50%;
      transform:translate(-50%,-50%);
    }

方案③:flex

    body{
      display: flex;
      justify-content: center;
      align-items: center;
    }

方案④:js实现居中

🚀思路:

  • 距离左侧距离(一屏幕宽度盒子宽度)➗2
  • 距离上侧距离(一屏幕高度盒子高度)➗2
//index.js实现
let wd  = document.documentElement.clientWidth;
let wh = document.documentElement.clientHeight;
let box = document.getElementById('box');
box.style.position = 'absolute';
box.style.left = (wd - 360)/2 + 'px';
box.style.top = (wh - 360)/2 + 'px';

3.scorll系列:

scroll:

  • scrollWidth:

    • 在没有内容溢出的情况下:scrollWidth等于clientWidth
    • 在有内容溢出的情况下:scrollWidth约等于真实内容的宽度
  • scorllHeight:

    • 在没有内容溢出的情况下:scrollHeight等于clientHeight

    • 在有内容溢出的情况下:scrollHeight约等于真实内容的高度

    所以,如果要获取整个页面真实的高度,可以通过:

    document.documentElement.scrollHeight || document.body.scrollHeight
    
  • scrollTop:

    • 获取纵向滚动条滚动条距离顶部的距离
    • 边界值:
      • min:0
      • max:整个的高度scrollHeight ➖ 一整个屏幕的高度clientHeight
  • scrollLeft:

    • 获取横向滚动条距离左侧的距离

4.offset相关:

offset:

  • offsetWidth:在clientWidth基础上加上border宽度
  • offsetHeight:在clientHeight基础上加上border宽度

下面单独记录下offsetParentoffsetLeftoffsetTop

offsetParent:获取父级参照物(不一定是父级元素)

🚀需要注意的是,父参照物和父级元素没有必然联系,父级参照物是同一个平面中,最外层元素是所有后代元素的参照物,而基于position:relative/absolute/fixed可以让元素脱离文档流(一个新平面),从而改变元素的父参照物

offsetTop:距离其父级参照物的上偏移

offsetLeft:距离其父级参照物的左偏移量(当前元素的外边框到父级参照物的里边框)

定位可以创造新的平面,从而改变父参照物,那么如何算一个元素距离body偏移量呢(如下图)?

/**
 * @function 获取当前元素距离body的left和top偏移
 *  @param {string} curEle
 *  @return {object:{top,left}} 
*/
function offset(curEle){
  // 获取父级参照物
  let par = curEle.offsetParent;
  let l = curEle.offsetLeft;
  let t = curEle.offsetTop;
  // tagName标签名都是大写的
  while(par && par.tagName !== 'BODY'){
    // 在原有基础上累加:父参照物的边框、父参照物的偏移量
    // ie8的偏移已经给border算进去了的,不需要自己再手动添加了的
    if(!/MSIE 8\.0/.test(window.navigator.userAgent)){
      l += par.clientLeft;
      t += par.clientTop;
    };
    l += par.offsetLeft
    t += par.offsetTop;
    //获取父级参照物,继续下一次循环
    par = par.offsetParent;
  }
  return {
    top:t,
    left:l
  }
}

感谢我家莎老板,很多很多也都包含在这句感谢里了,所以谢谢~