UNPKG

@jdcfe/yep-react

Version:

一套移动端的React组件库

271 lines (229 loc) 10.4 kB
"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; } };