标签:ssi ctp ready 检查 efault ret lun enter empty
import React from ‘react‘;
import { findDOMNode } from ‘react-dom‘;
import throttle from ‘lodash/throttle‘;
import { Spin } from ‘@wind/wind-ui‘;
import ReactPlaceHolder from ‘react-placeholder‘;
/**
* 需找当前元素最近可滚动的父元素
* @param {HTMLElement} element 当前元素
*/
function getScrollParent(element) {
// const style = (elem, prop) => {
// if (getComputedStyle !== undefined) {
// return getComputedStyle(elem, null).getPropertyValue(prop);
// }
// return elem.style[prop];
// };
// const overflow = node => style(node, ‘overflow‘) + style(node, ‘overflow-x‘) + style(node, ‘overflow-y‘);
// 循环判断父节点是否可滚动这里暂不添加,直接去直接父元素
if (!(element instanceof HTMLElement)) {
return window;
}
let parent = element;
while (parent) {
// 当前节点是body或者document
if (parent === document.body || parent === document.documentElement) {
break;
}
// 当期元素无父节点
if (!parent.parentNode) {
break;
}
// 判断节点是否含有overflow等属性的值
if (parent.scrollHeight > parent.clientHeight) {
return parent;
}
// if (/(scroll|auto|inherit)/.test(overflow(parent))) {
// return parent;
// }
parent = parent.parentNode;
}
return window;
}
let EmptyCompBox = ({ ...props }) => (
<div {...props}>
{/* <Spin size="large" className="lazyload-center-spin" /> */}
</div>
);
class ScrollLoad extends React.Component {
state = {
visible: false,
};
componentDidMount() {
let dom = findDOMNode(this); // 取得当前节点
let parent = getScrollParent(dom);
// console.log(dom,parent)
this.parent = parent;
let visible = this.checkVisible(dom, parent); // 初始化检查是否可见
visible();
this.scrollHandler = throttle(this.checkVisible(dom, parent), 100);
parent.addEventListener(‘scroll‘, this.scrollHandler, { passive: true });
}
componentWillUnmount() {
this.parent.removeEventListener(‘scroll‘, this.scrollHandler);
}
/**
* 获取当前节点的offsetTop,如果不是直接父节点的话,通过循环获取
*/
getNodeOffsetTop = (node, parent) => {
if (!node || !parent) {
this.setState({ visible: true });
return 0;
}
let current = node;
let offsetTop = 0;
offsetTop += current.offsetTop
// ==========ff================
// while (current !== parent && current) {
// offsetTop += current.offsetTop;
// current = current.parentElement;
// }
// ==========ff================
return offsetTop;
};
/**
* 检测元素是否可见
*/
checkVisible = (node, parent) => {
if (!node || !parent) {
this.setState({ visible: true });
return null;
}
return () => {
const { visible } = this.state;
// 一旦可见下次取消事件监听
if (visible) {
this.parent.removeEventListener(‘scroll‘, this.scrollHandler);
return; // 直接返回不执行当次eventListener
}
let seenHeight = parent.clientHeight || 0;
let scrollHeight = parent.scrollTop || 0;
let currentNode = findDOMNode(this); // 获取最新的dom结构
let offsetTop = this.getNodeOffsetTop(currentNode, parent);
// 1. 当偏移高度小于可见高度
// 2. 初始不可见的时候,当可视高度+滚动高度大于了偏移高度
// 3. 可以设置preLoad
// console.log(offsetTop, seenHeight, scrollHeight)
if (offsetTop <= seenHeight + scrollHeight) { //可视范围内
this.setState({ visible: true });
}
};
};
render() {
const { visible } = this.state;
const { id, className, style } = this.props;
return (
<ReactPlaceHolder
ready={visible}
customPlaceholder={<EmptyCompBox id={id} className={className} style={style} />}
>
{this.props.children}
</ReactPlaceHolder>
);
}
}
export default ScrollLoad;
标签:ssi ctp ready 检查 efault ret lun enter empty
原文地址:https://www.cnblogs.com/lisiyang/p/13667881.html