@jdcfe/yep-react
Version:
一套移动端的React组件库
271 lines (229 loc) • 10.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var React = _interopRequireWildcard(require("react"));
var _styleUtil = require("../_utils/styleUtil");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
var INDICATOR = {
activate: '释放更新',
deactivate: '下拉刷新',
release: '加载中...',
finish: '完成'
};
var PullToRefresh = /*#__PURE__*/function (_React$PureComponent) {
(0, _inherits2.default)(PullToRefresh, _React$PureComponent);
var _super = _createSuper(PullToRefresh);
function PullToRefresh(props) {
var _this;
(0, _classCallCheck2.default)(this, PullToRefresh);
_this = _super.call(this, props);
_this.containerRef = function (container) {
_this.container = container;
};
_this.triggerPullToRefresh = function () {
if (_this.props.refreshing) {
// change dom need after setState
_this.setState({
currentState: 'release'
}, function () {
return _this.setInfScrollStyle(_this.props.pullDownToRefreshThreshold + 1);
});
} else {
_this.setState({
currentState: 'finish'
}, function () {
return _this.reset();
});
}
};
_this.isMoveEdge = function () {
var container = _this.props.getScrollContainer();
if (container && container === document.body) {
var scrollNode = document.scrollingElement ? document.scrollingElement : document.body;
return scrollNode.scrollTop <= 0;
}
var refScrollTop = container && container.scrollTop || 0;
var tops = [window.pageYOffset || 0, document.documentElement.scrollTop, refScrollTop];
return Math.max.apply(Math, tops) <= 0;
};
_this.setInfScrollStyle = function (cs) {
if (_this.container) {
(0, _styleUtil.setTransform)(_this.container.style, "translate3d(0px,".concat(cs, "px,0)"));
}
};
_this.reset = function () {
_this.setInfScrollStyle(0);
requestAnimationFrame(function () {
_this.container.style.overflow = 'auto';
_this.container.style.transform = 'none';
_this.container.style.willChange = 'none';
});
};
_this.state = {
currentState: 'deactivate'
}; // variables to keep track of pull down behaviour
_this.startY = 0;
_this.startX = 0;
_this.currentY = 0;
_this.currentX = 0;
_this.dragging = false; // will be populated in componentDidMount
// based on the height of the pull down element
_this.onStart = _this.onStart.bind((0, _assertThisInitialized2.default)(_this));
_this.onMove = _this.onMove.bind((0, _assertThisInitialized2.default)(_this));
_this.onEnd = _this.onEnd.bind((0, _assertThisInitialized2.default)(_this));
return _this;
}
(0, _createClass2.default)(PullToRefresh, [{
key: "componentDidMount",
value: function componentDidMount() {
this.ele = this.props.getScrollContainer() || this.container;
this.ele.addEventListener('touchstart', this.onStart, {
passive: false
});
this.ele.addEventListener('touchmove', this.onMove, {
passive: false
});
this.ele.addEventListener('touchend', this.onEnd, {
passive: false
});
this.forceUpdate();
if (typeof this.props.refreshFunction !== 'function') {
throw new Error("Mandatory prop \"refreshFunction\" missing.\n Pull Down To Refresh functionality will not work\n as expected.'");
}
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
if (prevProps === this.props || prevProps.refreshing === this.props.refreshing) {
return;
}
this.triggerPullToRefresh();
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.ele.removeEventListener('touchstart', this.onStart);
this.ele.removeEventListener('touchmove', this.onMove);
this.ele.removeEventListener('touchend', this.onEnd);
}
}, {
key: "onStart",
value: function onStart(evt) {
this.dragging = true;
this.startY = evt.pageY || evt.touches[0].pageY;
this.startX = evt.pageX || evt.touches[0].pageX;
this.currentY = this.startY;
this.currentX = this.startX;
this.container.style.willChange = 'transform';
this.container.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)";
}
}, {
key: "onMove",
value: function onMove(evt) {
if (!this.dragging) return;
this.currentY = evt.pageY || evt.touches[0].pageY;
this.currentX = evt.pageX || evt.touches[0].pageX; // user is scrolling down to up
if (this.currentY < this.startY) return; // 当前点与起始点形成的角度大于30度且小于150度时,下拉;其他情况不处理。
// 公式: (startY-currY)/(startX-currX)>1/√3~=0.58
// console.log("onMove evt", this.currentX, this.startX, this.currentY, this.startY);
if (this.currentX !== this.startX) {
var bi = Math.abs((this.startY - this.currentY) / (this.startX - this.currentX));
if (bi < 0.58) {
// console.log('不能下拉呀');
return;
}
}
if (this.isMoveEdge()) {
//禁止整个页面下拉效果
evt.preventDefault();
evt.stopPropagation();
if (this.currentY - this.startY >= this.props.pullDownToRefreshThreshold) {
if (this.state.currentState === 'deactivate') {
this.setState({
currentState: 'activate'
});
}
} else {
if (this.state.currentState !== 'deactivate') {
this.setState({
currentState: 'deactivate'
});
}
}
if (this.currentY - this.startY > this.props.maxPullDownDistance) return;
this.container.style.overflow = 'visible';
this.setInfScrollStyle(this.currentY - this.startY);
}
}
}, {
key: "onEnd",
value: function onEnd() {
this.startY = 0;
this.startX = 0;
this.currentY = 0;
this.currentX = 0;
this.dragging = false;
if (this.state.currentState === 'activate') {
this.setState({
currentState: 'release'
});
this.props.refreshFunction && this.props.refreshFunction();
} else {
this.reset();
}
}
}, {
key: "render",
value: function render() {
var _this$props = this.props,
prefixCls = _this$props.prefixCls,
className = _this$props.className,
style = _this$props.style,
indicator = _this$props.indicator,
children = _this$props.children;
var componentStyle = Object.assign({
height: 'auto',
overflow: 'hidden',
WebkitOverflowScrolling: 'touch'
}, style);
var outerDivStyle = {
overflow: 'auto'
};
return /*#__PURE__*/React.createElement("div", {
style: outerDivStyle
}, /*#__PURE__*/React.createElement("div", {
className: className,
ref: this.containerRef,
style: componentStyle
}, /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-indicator")
}, indicator[this.state.currentState] || INDICATOR[this.state.currentState]), children));
}
}]);
return PullToRefresh;
}(React.PureComponent);
exports.default = PullToRefresh;
PullToRefresh.defaultProps = {
pullDownToRefreshThreshold: 50,
maxPullDownDistance: 100,
disableBrowserPullToRefresh: true,
style: {},
prefixCls: 'Yep-pull-to-refresh',
indicator: INDICATOR,
getScrollContainer: function getScrollContainer() {
return undefined;
}
};