dom、js原生常用api, 兼容ie等主流浏览器(持续更新)

发布时间 2023-05-23 21:02:31作者: william_new

开发组件库必须知道的东西

/**
 * 获取scrollTop
 * @param  { HTMLElement | window } element - dom元素或者window对象
 * @returns { number }
 */
function getScrollTop(element) {
  if (element === window) {
    return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
  }
  return element.scrollTop
}

/**
 * 获取元素的样式
 * @param  { HTMLElement } element - dom元素
 * @param  { string } styleName - 样式属性名称
 * @param  { pseudoElement } pseudoElement=null  - 伪类名称
 * @returns { string }
 * - defaultView:
 * Firefox 3.6 上访问子框架内的样式 (iframe)必须加defaultView
 * IE8 浏览器中 document.defaultView !== window
 */
function getStyle(element, styleName, pseudoElement = null) {
  if (!element || !styleName) return ''
  const isLessIe9 = Number(document.documentMode) < 9
  // ie9以下float属性名为styleFloat
  const alias = {
    float: isLessIe9 ? 'styleFloat' : 'cssFloat',
  }
  if (Object.prototype.hasOwnProperty.call(alias, styleName)) styleName = alias[styleName]

  try {
    //获取到的一定是字符串,所以不用考虑0为false的情况
    const str = element.style[styleName]
    if (str) return str //行内样式
    // ie || 其它 || 异常
    let styleObj = element.currentStyle || document.defaultView.getComputedStyle(element, pseudoElement) || {}
    return styleObj[styleName] || ''
  } catch (error) {
    return element.style[styleName]
  }
}

/**
 * 获取指定元素所在滚动容器
 * @param  { HTMLElement } element  - dom元素
 * @param  { boolean } isVertical=true  - 是否是垂直方向,默认true
 * @returns { HTMLElement | window }
 */
function getScrollEventTarget(element, isVertical = true) {
  let currentNode = element
  while (currentNode) {
    if ([window, document, document.documentElement].includes(currentNode)) {
      return window
    }
    if (currentNode instanceof Element) {
      const styleName = isVertical ? 'overflowY' : 'overflow-x'
      if (['scroll', 'auto', 'overlay'].includes(getStyle(currentNode, styleName))) {
        return currentNode
      }
    }
    currentNode = currentNode.parentNode
  }
  return currentNode
}