目录
前言
在平时的开发过程中,合理使用一些API,可以在一定程度上帮助我们提升开发效率。接下来我跟大家介绍一下3个前端开发中比较好用的API。
正文
一、getComputedStyle()
介绍
DOM2 Style 在 document.defaultView 上增加了 getComputedStyle() 方法,该方法返回一个 CSSStyleDeclaration 对象(与 style 属性的类型一样),包含元素的计算样式。
使用
  
   - 
    
     
    
    
     
      document.
      defaultView.
      getComputedStyle(element[,pseudo-element])
     
    
- 
    
     
    
    
     
      // 或者是
     
    
- 
    
     
    
    
     
      window.
      getComputedStyle(element[,pseudo-element])
     
    
这个方法接收两个参数:需要取得计算样式的元素、伪元素字符串(如":after")。如果不需要查询伪元素,则第二个参数可以传 null。
  
   - 
    
     
    
    
     
      <!DOCTYPE html>
     
    
- 
    
     
    
    
     
      <html>
     
    
- 
    
     
    
    
       
      <head>
     
    
- 
    
     
    
    
         
      <style type="text/css">
      
     
    
- 
    
     
    
    
           
      #myDiv {
     
    
- 
    
     
    
    
             
      background-color: blue;
     
    
- 
    
     
    
    
             
      width: 
      100px;
     
    
- 
    
     
    
    
             
      height: 
      200px;
     
    
- 
    
     
    
    
     
            }
     
    
- 
    
     
    
    
         
      </style>
     
    
- 
    
     
    
    
       
      </head>
     
    
- 
    
     
    
    
       
      <body>
     
    
- 
    
     
    
    
         
      <div id="myDiv" style="background-color:red;border:1px solid black">
      </div>
     
    
- 
    
     
    
    
       
      </body>
     
    
- 
    
     
    
    
       
      <script>
      
     
    
- 
    
     
    
    
         
      function 
      getStyleByAttr(
      obj, name) {
     
    
- 
    
     
    
    
           
      return 
      window.
      getComputedStyle ? 
      window.
      getComputedStyle(obj, 
      null)[name] : obj.
      currentStyle[name]
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      let node = 
      document.
      getElementById(
      'myDiv')
     
    
- 
    
     
    
    
         
      console.
      log(
      "backgroundColor: ",
      getStyleByAttr(node, 
      'backgroundColor'))
     
    
- 
    
     
    
    
         
      console.
      log(
      "width: ",
      getStyleByAttr(node, 
      'width'))
     
    
- 
    
     
    
    
         
      console.
      log(
      "height :",
      getStyleByAttr(node, 
      'height'))
     
    
- 
    
     
    
    
         
      console.
      log(
      "border :",
      getStyleByAttr(node, 
      'border'))
     
    
- 
    
     
    
    
       
      </script>
     
    
- 
    
     
    
    
     
      </html>
     
    
控制台打印

与 element.style 的异同
相同点
二者返回的都是 CSSStyleDeclaration 对象;
不同点
(1)element.style 读取的只是元素的内联样式,即写在元素的 style 属性上的样式;而 getComputedStyle 读取的样式是最终样式,包括了内联样式、嵌入样式和外部样式。

如上,由于 background-color 既在行内样式,也在嵌入样式设置,且行内样式优先级高,最终样式为 red,则 getComputedStyle 得出的也是 red。

(2)element.style 既支持读也支持写,我们通过 element.style 即可改写元素的样式。而 getComputedStyle 仅支持读并不支持写入。我们可以通过使用 getComputedStyle 读取样式,通过 element.style 修改样式。
二、getBoundingClientRect()
介绍
getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。
使用
let DOMRect = element.getBoundingClientRect()它的返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合,就是该元素的 CSS 边框大小。返回的结果是包含完整元素的最小矩形,并且拥有 left,top,right,bottom,x,y,width 和 height 这几个以像素为单位的只读属性用于描述整个边框。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

如下,对例一的红色块位置信息进行打印
  
   - 
    
     
    
    
     
      let node = 
      document.
      getElementById(
      'myDiv')
     
    
- 
    
     
    
    
     
      console.
      log(
      "positionMsg: ",node.
      getBoundingClientRect())
     
    

可轻松获得相关信息。
场景一:获取 dom 元素相对于网页左上角定位的距离
以前的写法是通过 offsetParent 找到元素到定位父级元素,直至递归到顶级元素 body 或 html。
  
   - 
    
     
    
    
     
      // 获取dom元素相对于网页左上角定位的距离
     
    
- 
    
     
    
    
     
      function 
      offset(
      el) {
     
    
- 
    
     
    
    
       
      let top = 
      0
     
    
- 
    
     
    
    
       
      let left = 
      0
     
    
- 
    
     
    
    
       
      do {
     
    
- 
    
     
    
    
     
          top += el.
      offsetTop
     
    
- 
    
     
    
    
     
          left += el.
      offsetLeft
     
    
- 
    
     
    
    
     
        } 
      while ((el = el.
      offsetParent))   
      // 存在兼容性问题
     
    
- 
    
     
    
    
       
      return {
     
    
- 
    
     
    
    
         
      top: top,
     
    
- 
    
     
    
    
         
      left: left
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      let odiv = 
      document.
      getElementsByClassName(
      'markdown-body')
     
    
- 
    
     
    
    
     
      offset(a[
      0])   
      // {top: 271, left: 136}
     
    
使用 getBoundingClientRect() :
  
   - 
    
     
    
    
     
      let left = element.
      getBoundingClientRect().
      left + 
      document.
      documentElement.
      scrollLeft
     
    
- 
    
     
    
    
     
      let top = element.
      getBoundingClientRect().
      top + 
      document.
      documentElement.
      scrollTop
     
    
场景二:判断元素是否在可视区域内
  
   - 
    
     
    
    
     
      function 
      isElView(
      el) {
     
    
- 
    
     
    
    
       
      let top = el.
      getBoundingClientRect().
      top   
      // 元素顶端到可见区域顶端的距离
     
    
- 
    
     
    
    
       
      let bottom = el.
      getBoundingClientRect().
      bottom   
      // 元素底部端到可见区域顶端的距离
     
    
- 
    
     
    
    
       
      let viewH = 
      document.
      documentElement.
      clientHeight   
      // 浏览器可见区域高度。
     
    
- 
    
     
    
    
       
      if (top < viewH && bottom > 
      0) {
     
    
- 
    
     
    
    
         
      return 
      true
     
    
- 
    
     
    
    
     
        } 
      else 
      if (top >= viewH || bottom <= 
      0) {
     
    
- 
    
     
    
    
         
      // 不可见
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
       
      return 
      false
     
    
- 
    
     
    
    
     
      }
     
    
三、requestAnimationFrame()
介绍
window.requestAnimationFrame() 告诉浏览器你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
使用
window.requestAnimationFrame(callback)兼容性处理
  
   - 
    
     
    
    
     
      window.
      _requestAnimationFrame = (
      function (
      ) {
     
    
- 
    
     
    
    
       
      return (
     
    
- 
    
     
    
    
         
      window.
      requestAnimationFrame ||
     
    
- 
    
     
    
    
         
      window.
      webkitRequestAnimationFrame ||
     
    
- 
    
     
    
    
         
      window.
      mozRequestAnimationFrame ||
     
    
- 
    
     
    
    
         
      function (
      callback) {
     
    
- 
    
     
    
    
           
      window.
      setTimeout(callback, 
      1000 / 
      60)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
        )
     
    
- 
    
     
    
    
     
      })()
     
    
结束动画
  
   - 
    
     
    
    
     
      let globalID
     
    
- 
    
     
    
    
     
      function 
      animate(
      ) {
     
    
- 
    
     
    
    
       
      // 一直运行
     
    
- 
    
     
    
    
     
        globalID = 
      requestAnimationFrame(animate)   
      // Do something animate
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
     
      globalID = 
      requestAnimationFrame(animate)   
      //开始
     
    
- 
    
     
    
    
     
      cancelAnimationFrame(globalID)   
      //结束
     
    
与 setTimeout 相比,requestAnimationFrame 最大的优势是由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是 60Hz,那么回调函数就每 16.7ms 被执行一次,如果刷新率是 75Hz,那么这个时间间隔就变成了 1000/75=13.3ms,换句话说就是,requestAnimationFrame 的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。这个 API 的调用很简单,如下所示:
  
   - 
    
     
    
    
     
      let progress = 
      0
     
    
- 
    
     
    
    
     
      // 回调函数
     
    
- 
    
     
    
    
     
      function 
      render(
      ) {
     
    
- 
    
     
    
    
     
        progress += 
      1   
      // 修改进度条的位置
     
    
- 
    
     
    
    
       
      if (progress < 
      100) {
     
    
- 
    
     
    
    
         
      // 在进度条没有结束前,递归渲染
     
    
- 
    
     
    
    
         
      window.
      requestAnimationFrame(render)
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
     
      // 第一帧渲染
     
    
- 
    
     
    
    
     
      window.
      requestAnimationFrame(render)
     
    
优点
-  CPU 节能:使用 setTimeout 实现的动画,当页面被隐藏或最小化时,setTimeout 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费 CPU 资源。而 requestAnimationFrame 则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的 requestAnimationFrame 也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了 CPU 开销。 
-  函数节流:在高频率事件(resize,scroll 等)中,为了防止在一个刷新间隔内发生多次函数执行,使用 requestAnimationFrame 可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销。一个刷新间隔内函数执行多次时没有意义的,因为显示器每 16.7ms 刷新一次,多次绘制并不会在屏幕上体现出来。 
场景一:监听 scroll 函数
页面滚动事件(scroll)的监听函数,就很适合用这个 api,推迟到下一次重新渲染。
  
   - 
    
     
    
    
     
      $(
      window).
      on(
      'scroll', 
      function (
      ) {
     
    
- 
    
     
    
    
       
      window.
      requestAnimationFrame(scrollHandler)
     
    
- 
    
     
    
    
     
      })
     
    
平滑滚动到页面顶部
  
   - 
    
     
    
    
     
      const 
      scrollToTop = (
      ) => {
     
    
- 
    
     
    
    
       
      const c = 
      document.
      documentElement.
      scrollTop || 
      document.
      body.
      scrollTop
     
    
- 
    
     
    
    
       
      if (c > 
      0) {
     
    
- 
    
     
    
    
         
      window.
      requestAnimationFrame(scrollToTop)
     
    
- 
    
     
    
    
         
      window.
      scrollTo(
      0, c - c / 
      8)   
      // 每次网上滚动 1/8,每一帧平滑
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      scrollToTop()
     
    
场景二、大量数据渲染
比如对十万条数据进行渲染,主要由以下几种方法:
(1)使用定时器
  
   - 
    
     
    
    
     
      // 需要插入的容器
     
    
- 
    
     
    
    
     
      let ul = 
      document.
      getElementById(
      'container')
     
    
- 
    
     
    
    
     
      // 插入十万条数据
     
    
- 
    
     
    
    
     
      let total = 
      100000
     
    
- 
    
     
    
    
     
      // 一次插入 20 条
     
    
- 
    
     
    
    
     
      let once = 
      20
     
    
- 
    
     
    
    
     
      // 总页数
     
    
- 
    
     
    
    
     
      let page = total / once
     
    
- 
    
     
    
    
     
      // 每条记录的索引
     
    
- 
    
     
    
    
     
      let index = 
      0
     
    
- 
    
     
    
    
     
      // 循环加载数据
     
    
- 
    
     
    
    
     
      function 
      loop(
      curTotal, curIndex) {
     
    
- 
    
     
    
    
       
      if (curTotal <= 
      0) {
     
    
- 
    
     
    
    
         
      return 
      false
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
       
      // 每页多少条
     
    
- 
    
     
    
    
       
      let pageCount = 
      Math.
      min(curTotal, once)
     
    
- 
    
     
    
    
       
      setTimeout(
      () => {
     
    
- 
    
     
    
    
         
      for (
      let i = 
      0; i < pageCount; i++) {
     
    
- 
    
     
    
    
           
      let li = 
      document.
      createElement(
      'li')
     
    
- 
    
     
    
    
     
            li.
      innerText = curIndex + i + 
      ' : ' + ~~(
      Math.
      random() * total)
     
    
- 
    
     
    
    
     
            ul.
      appendChild(li)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      loop(curTotal - pageCount, curIndex + pageCount)
     
    
- 
    
     
    
    
     
        }, 
      0)
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
     
      loop(total, index)
     
    
(2)使用 requestAnimationFrame
  
   - 
    
     
    
    
     
      // 需要插入的容器
     
    
- 
    
     
    
    
     
      let ul = 
      document.
      getElementById(
      'container')
     
    
- 
    
     
    
    
     
      // 插入十万条数据
     
    
- 
    
     
    
    
     
      let total = 
      100000
     
    
- 
    
     
    
    
     
      // 一次插入 20 条
     
    
- 
    
     
    
    
     
      let once = 
      20
     
    
- 
    
     
    
    
     
      // 总页数
     
    
- 
    
     
    
    
     
      let page = total / once
     
    
- 
    
     
    
    
     
      // 每条记录的索引
     
    
- 
    
     
    
    
     
      let index = 
      0
     
    
- 
    
     
    
    
     
      // 循环加载数据
     
    
- 
    
     
    
    
     
      function 
      loop(
      curTotal, curIndex) {
     
    
- 
    
     
    
    
       
      if (curTotal <= 
      0) {
     
    
- 
    
     
    
    
         
      return 
      false
     
    
- 
    
     
    
    
     
        }
     
    
- 
    
     
    
    
       
      // 每页多少条
     
    
- 
    
     
    
    
       
      let pageCount = 
      Math.
      min(curTotal, once)
     
    
- 
    
     
    
    
       
      window.
      requestAnimationFrame(
      function (
      ) {
     
    
- 
    
     
    
    
         
      for (
      let i = 
      0; i < pageCount; i++) {
     
    
- 
    
     
    
    
           
      let li = 
      document.
      createElement(
      'li')
     
    
- 
    
     
    
    
     
            li.
      innerText = curIndex + i + 
      ' : ' + ~~(
      Math.
      random() * total)
     
    
- 
    
     
    
    
     
            ul.
      appendChild(li)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      loop(curTotal - pageCount, curIndex + pageCount)
     
    
- 
    
     
    
    
     
        })
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
     
      loop(total, index)
     
    
总结
以上就是几个不错的API,在某些场景下使用能大大提高我们的开发效率,赶紧用起来吧。
转载:https://blog.csdn.net/qq_41809113/article/details/125626444
