当咱们一次性大批量的加载资源的时候,会占用大量的内存,尤为是在一些低内存的设备上会形成卡顿的现象,因此咱们就须要在必要的时候再进行资源的加载。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。