准备工作:
- 了解各个高度的猫腻
- window对象
innerWidth、innerHeight、pageXOffset、pageYOffset、scrollX、scrollY - window.screen
- document对象
document.documentElement/body.clientHeight、clientWidth - HTMLElement的
offsetTop、offsetLeft、offsetHeight、offsetWidth - document.scrollingElement
- window对象
- 滚动监听
window.pageYOffset == window.scrollY
在标准模式下, 这是文档的根元素, document.documentElement。 当在怪异模式下, scrollingElement 属性返回 HTML body 元素(若不存在返回 null )。
window尺寸
| ex. | 说明 | 兼容 |
|---|---|---|
| window.innerHeight[innerWidth] | 浏览器窗口的内部高度(包括滚动条),可见高度 | Internet Explorer、Chrome、Firefox、Opera 以及 Safari |
| window.pageYOffset[X] 是 window.scrollY[X] 的别名 | 文档从顶部开始滚动过的像素值 | 为了跨浏览器兼容,请使用 window.pageYOffset 代替 window.scrollY。另外,旧版本IE(<9)两个属性都不支持 |
| document.documentElement.clientHeight[clientWidth] | document.documentElement为当前文档的直接子节点,可见高度 | Internet Explorer 8、7、6、5 |
| document.body.clientHeight[clientWidth] | 当前文档的 <body> 或 <frameset> 节点,可见高度 |
Internet Explorer 8、7、6、5 |
| HTMLElement.offsetHeight[offsetWidth] | 返回该元素的像素高度,高度包含该元素的垂直内边距、边框和元素的水平滚动条(如果存在且渲染的话),不包含:before或:after等伪类元素的高度,且是一个整数。如果被隐藏,display:none,则返回0 | |
| HTMLElement.offsetLeft[offsetTop] | 它返回当前元素相对于其 offsetParent 元素的顶部内边距的距离 |
完整兼容性代码
窗口内可见高度
let w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
文档从顶部[左侧边]开始滚动过的像素值
let supportPageOffset = window.pageXOffset !== undefined;
let isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
let x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
let y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
图片懒加载
实现图片懒加载的React组件
支持单张图片懒加载,需要固定宽高的占位,没有加节流
/**
* loadImage: 占位图片
* imageSrc: 实际图片地址
* height: 确定图片高度
*/
import React, { Component } from 'react'
import tempImage from './icon-loading.gif'
import styles from './style.less'
class lazyloadImage extends Component {
constructor(props) {
super(props)
this.state = {
showImage: false,
}
}
// 一定要有占位图片,有一个占位高度
render() {
const imageSrc = this.state.showImage ? this.props.imageSrc : this.props.loadImage
return (
<div className={styles.imageBox} ref="image" style={{ height: this.props.height }}>
<img src={imageSrc} alt="" />
</div>
)
}
componentDidMount() {
<!-- 首屏加载,在没有滚动的情况下保证首屏的加载 -->
this.scrollEvent()
<!--添加滚动监听,需要的话,可以自己加节流-->
window.addEventListener('scroll', this.scrollEvent, false)
}
scrollEvent = () => {
const el = this.refs.image
<!--文档从顶部开始滚动过的像素值-->
const viewTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
<!--视口可见高度-->
const viewHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
<!--当前元素相对于其 offsetParent 元素的顶部内边距的距离-->
const elTop = el.offsetTop
<!--当前组件中div的占位高度-->
const elHeight = el.offsetHeight
if (elTop + elHeight >= viewTop && elTop + elHeight <= viewHeight + viewTop) {
this.loadImage()
}
}
loadImage = () => {
this.setState({ showImage: true })
window.removeEventListener('scroll', this.scrollEvent)
}
}
lazyloadImage.defaultProps = {
loadImage: tempImage,
imageSrc: '',
height: 400,
}
export default lazyloadImage