Skip to content

谈谈 JavaScriptclientoffsetscroll 三大家族 #4

@guilixie

Description

@guilixie

说来话长,首先当然要从盒子模型谈起

盒子模型

  • 标准盒子模型
  1. width === content width,
     height === content height
  2. box width === width + padding + border,
     box height === height + padding + border
  • IE 盒子模型
  1. width === box width,
     height === box height
  2. width and height,both include padding and border
  3. content width === width - padding - border,
     content height === height - padding - border

注意:css3 box-sizing 改变盒模型

offset 家族

1. offsetWidth and offsetHeight, are both readonly

// 标准盒子模型
box.offsetWidth === width + padding + border
box.offsetHeight === height + padding + border

// IE盒子模型
box.offsetWidth === width
box.offsetHeight === height

2. offsetLeft and offsetTop

offsetLeft: 获取自己左边框外侧与offsetParent的左边框内侧的距离
offsetTop: 获取自己上边框外侧与offsetParent的上边框内侧的距离

3. offsetParent(自己定位参照的(position!==static)父元素)

  • 元素固定定位(fixed)=> offsetParent === null
  • 元素非固定定位,并且所有祖先元素没有定位 => offsetParent === body
  • body  => offsetParent === null

4. jQuery 获取宽高

  • width()/height(): 内容宽高

    • 标准盒子:width/height
    • IE 盒子:width/height - padding - border
  • innerWidth()/innerHeight(): 内容宽高 +  padding

  • outerWidth()/outerHeight(): 内容宽高 + padding + border

    • 标准盒子:width/height + padding + border
    • IE 盒子:width/height
  • 获取可视区域的宽高: $(window).width() / $(window).height()

  • offset(): 获取元素距离 document 的位置,不传参是获取,传参是设置

function offset(el) {
  let top = 0
  let left = 0

  while (el.offsetParent) {
    top += el.offsetTop
    left += el.offsetLeft
    el = el.offsetParent
  }

  return {
    top: top,
    left: left
  }
}

scroll 家族

1. scrollWidth and scrollHeight

元素内容的真实宽高,包括由于溢出而无法展示在网页的不可见部分,不包括paddingborder

2. scrollLeft and scrollTop

  scrollLeft:onscroll事件触发,元素向左卷出去的距离
  scrollTop:onscroll事件触发,元素向上卷出去的距离

3. jQuery 的scrollLeft()scrollTop()

与原生 JS 一致

function scrollLeft(el, num) {
  if (num != null) {
    el.scrollLeft = num
  } else {
    return el.scrollLeft
  }
}

function scrollTop(el, num) {
  if (num != null) {
    el.scrollTop = num
  } else {
    return el.scrollTop
  }
}

client 家族

1. clientWidth and clientHeight

获取元素可视区域(内容)宽高

// 获取界面可视区域宽高(兼容IE)
function getClientSize() {
  let w = 0
  let h = 0
  if (window.innerHeight !== undefined) {
    w = window.innerWidth
    h = window.innerHeight
  } else if (document.compatMode === 'CSS1Compat') {
    //判断是否有dtd约束
    ;(w = document.documentElement.clientWidth),
      (h = document.documentElement.clientHeight)
  } else {
    ;(w = document.body.clientWidth), (h = document.body.clientHeight)
  }
  return {
    width: w,
    height: h
  }
}

2. clientLeft and clientTop

左边框 border-left-width 和上边框 border-top-width

3. clientX and clientY

  clientY:event调用,鼠标距离浏览器可视区域的顶部距离
  clientX:event调用,鼠标距离浏览器可视区域的左边距离

3. jQuery 的position()方法

获取元素距离自己定位参照的父元素(offsetParent)的位置

function position(el) {
  return {
    top: el.offsetTop,
    left: el.offsetLeft
  }
}

总结

  1. 原生 JS 的scrollLeftscrollTop和 jQuery 的同名方法是一致的
  2. 原生 JS 的offsetLeftoffsetTop和 jQuery 的position()方法是一致的
  3. 原生 JS 的clientWidthclientHeight其实和 jQuery 的width()height()是一致的

Metadata

Metadata

Assignees

No one assigned

    Labels

    DOMDocument Object Model

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions