dora-ui
Version:
A React.js Mobile UI Library
189 lines (162 loc) • 5.75 kB
JavaScript
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import React, { Component, cloneElement } from 'react';
import { CSSTransition } from 'react-transition-group';
import PropTypes from 'prop-types';
import cx from 'classnames';
import debounce from 'lodash/debounce';
import Portal from '../portal';
import Spinner from '../spinner';
// 是否延迟spinning
function shouldDelay(spinning, delay) {
/* eslint-disable-next-line no-restricted-globals */
return !!spinning && !!delay && !isNaN(Number(delay));
}
var prefixCls = 'dora-spin';
var Spin =
/*#__PURE__*/
function (_Component) {
_inherits(Spin, _Component);
function Spin(_props) {
var _this;
_classCallCheck(this, Spin);
_this = _possibleConstructorReturn(this, _getPrototypeOf(Spin).call(this, _props));
_defineProperty(_assertThisInitialized(_this), "debouncifyUpdateSpinning", function (props) {
var delay = props.delay;
if (delay) {
// 取消防抖函数的执行
_this.cancelExistingSpin();
_this.updateSpinning = debounce(_this.updateSpinning, delay);
}
});
_defineProperty(_assertThisInitialized(_this), "updateSpinning", function () {
var spinning = _this.props.spinning;
var currentSpinning = _this.state.spinning;
if (currentSpinning !== spinning) {
_this.setState({
spinning: spinning
});
}
});
var _spinning = _props.spinning,
_delay = _props.delay;
var shouldBeDelayed = shouldDelay(_spinning, _delay);
_this.state = {
spinning: _spinning && !shouldBeDelayed
};
_this.debouncifyUpdateSpinning(_props);
return _this;
}
_createClass(Spin, [{
key: "componentDidMount",
value: function componentDidMount() {
this.updateSpinning();
}
/**
* antd Spin组件每次didupdate中 取消防抖updateSpinning函数的执行 随后重新创建防抖updateSpinning函数进行执行
* 未直接使用 didmount 中创建的防抖updateSpinning函数 的防抖特性 可参见antd源码3.20.5
* 此处进行优化: 利用防抖函数特性,无需重复取消创建防抖updateSpinning函数
*/
}, {
key: "componentDidUpdate",
value: function componentDidUpdate() {
this.updateSpinning();
}
/**
* 避免组件卸载后 spinning状态变化而setState报错
* 参考antd,相关issue https://github.com/ant-design/ant-design/pull/16081
*/
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.cancelExistingSpin();
}
}, {
key: "cancelExistingSpin",
value: function cancelExistingSpin() {
var updateSpinning = this.updateSpinning;
var copyUpdateSpinning = updateSpinning;
if (copyUpdateSpinning && copyUpdateSpinning.cancel) {
copyUpdateSpinning.cancel();
}
}
}, {
key: "getSpinElement",
value: function getSpinElement() {
var _this$props = this.props,
spinner = _this$props.spinner,
tip = _this$props.tip,
size = _this$props.size,
fullScreen = _this$props.fullScreen,
transition = _this$props.transition;
var isDefaultSpinner = spinner.type === Spinner;
var spinning = this.state.spinning;
var spinnerContainerCls = cx("".concat(prefixCls, "-spinner-container"), _defineProperty({}, "".concat(prefixCls, "-spinner-container__full"), fullScreen));
var tipCls = cx("".concat(prefixCls, "-text"), "".concat(prefixCls, "-text-").concat(size));
var spinElement = React.createElement("div", {
className: spinnerContainerCls
}, isDefaultSpinner ? cloneElement(spinner, {
size: size
}) : spinner, tip && React.createElement("div", {
className: tipCls
}, tip));
/* 是否为全屏展示 */
if (fullScreen) {
spinElement = React.createElement(Portal, null, spinElement);
}
/* 是否存在过渡效果 */
if (transition) {
return React.createElement(CSSTransition, {
in: spinning,
classNames: "dora-fade",
timeout: 300,
unmountOnExit: true
}, spinElement);
}
if (spinning) {
return spinElement;
}
return null;
}
}, {
key: "render",
value: function render() {
var _this$props2 = this.props,
wrapperClassName = _this$props2.wrapperClassName,
children = _this$props2.children;
var wrapperCls = cx(wrapperClassName, prefixCls);
return React.createElement("div", {
className: wrapperCls
}, this.getSpinElement(), children);
}
}]);
return Spin;
}(Component);
_defineProperty(Spin, "propTypes", {
spinning: PropTypes.bool.isRequired,
fullScreen: PropTypes.bool,
size: PropTypes.oneOf(['sm', 'md', 'lg']),
children: PropTypes.node,
spinner: PropTypes.element,
tip: PropTypes.string,
wrapperClassName: PropTypes.string,
transition: PropTypes.bool,
delay: PropTypes.number
});
_defineProperty(Spin, "defaultProps", {
fullScreen: true,
size: 'md',
tip: '',
wrapperClassName: '',
transition: true,
delay: 0,
spinner: React.createElement(Spinner, {
type: "wave"
})
});
export default Spin;