當咱們一次性大批量的加載資源的時候,會佔用大量的內存,尤爲是在一些低內存的設備上會形成卡頓的現象,因此咱們就須要在必要的時候再進行資源的加載。html
懶加載就是在真正須要資源才加載資源,這樣就能夠節省內存,儘量的減小卡頓現象的出現。node
懶加載的原理就如上圖所示,當組件進入可視區域加載子組件,不在可視區域內卸載子組件。懶加載的原理就是這麼簡單,下面介紹一下懶加載具體的實現方法。react
1. 計算子組件是否在可視區域以內git
const checkVisible = (component,offset=100,parent) => {
//獲取實際的DOM const node = ReactDOM.findDOMNode(component)
//獲取距離頂部的距離 const {top} = node.getBoundingClientRect() const windowHeight = window.innerHeight || document.documentElement.clientHeight const {top:parentTop,bottom:parentBottom } = parent.getBoundingClientRect()
//可視區域頂部的位置 const finalTop = Math.max(parentTop,0)
//可視區域底部的位置 const finalBottom = Math.min(parentBottom,windowHeight)
//計算是否在可視區域以內 if(top > finalTop - 100 && top < finalBottom + 100){ return true } return false }
2. 添加滾動事件github
首先咱們先利用上面的函數檢查檢查子組件是否在可視區域內,若是是則設置isVisible爲true,則顯示組件,不然不顯示組件。dom
checkedVisible(parent){
//是否只懶加載一次,once爲true 加載以後再也不操做dom const once = this.props.once ; const offset = this.props.offset return throttle(()=>{ const visibleState = this.state.isVisible if(!(once && visibleState)){ const isVisible = checkVisible(this,offset,parent) this.setState({isVisible}) } },200) }
const parent = getScrollParent(node); const checkedVisibleFn = this.checkedVisible(parent) ; //添加滾動事件 window.addEventListener("scroll",checkedVisibleFn,false)
爲window對象添加滾動事件,爲防止滾動事件頻繁觸發checkedVisible,咱們爲檢查checkVisible函數節流,減小性能開銷。此處咱們利用的throttle函數,更多關於節流函數和函數去抖的介紹可參考這邊博客:JS魔法堂:函數節流(throttle)與函數去抖(debounce)。函數
3. 獲取可滾動的父組件post
當前咱們只是爲考慮了window對象可滾動的狀況,若是是DOM對象可滾動咱們就須要獲取可滾動的父對象,而不僅是僅僅window對象。性能
//獲取滾動的父元素 const getScrollParent = (node) => { if(!node){ return document.documentElement } let parent = node ; //正則 const overflowReg = /(scroll|auto)/ while(parent){ if(!parent.parentNode){ return document.documentElement } const {overflow} = window.getComputedStyle(parent) if(overflowReg.test(overflow)){ return parent } parent = parent.parentNode } return document.documentElement } export default getScrollParent
4. 再次添加滾動事件this
若是不單單是window可滾動咱們在添加滾動事件以前進行一次判斷。
const node = ReactDOM.findDOMNode(this) ; const parent = getScrollParent(node); const checkedVisibleFn = this.checkedVisible(parent) ; if(parent === document.documentElement){ window.addEventListener("scroll",checkedVisibleFn,false) }else{ parent.addEventListener("scroll",checkedVisibleFn,false) }
以上基本就是react懶加載基本實現的方法,具體的代碼以及demo,能夠參考源碼:https://github.com/volcanoliuc/react-lazyload-demo
此demo僅僅只是簡化版的react懶加載,若是是在實際的項目中須要使用推薦使用 react-lazyload。