diff --git a/README.md b/README.md index 45f0764..28b70a7 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ see example | name | description | type | default | |----------|----------------|----------|--------------| -| direction | pull direction, can be `up` or `down` | String | `down` | +| direction | pull direction, can be `up` or `down` or `up_down` | String | `down` | | distanceToRefresh | distance to pull to refresh | number | 50 | | refreshing | Whether the view should be indicating an active refresh | bool | false | | onRefresh | Called when the view starts refreshing. | () => void | - | diff --git a/assets/index.less b/assets/index.less index 7d905f2..25b74df 100644 --- a/assets/index.less +++ b/assets/index.less @@ -6,6 +6,7 @@ overflow: hidden; } transform-origin: left top 0px; + position: relative; } &-transition { @@ -17,6 +18,9 @@ text-align: center; height: 25px; line-height: 25px; + position: static; + bottom: 0; + width: 100%; } &-down .@{pull-to-refresh}-indicator { @@ -24,6 +28,7 @@ } &-up .@{pull-to-refresh}-indicator { + position: absolute; margin-bottom: -25px; } } diff --git a/examples/base.js b/examples/base.js index 60669f8..d1b35cf 100644 --- a/examples/base.js +++ b/examples/base.js @@ -28,7 +28,7 @@ class App extends React.Component { style={{ height: 200, overflow: 'auto', border: '1px solid #ccc' }} {...(this.state.switchContainer ? { getScrollContainer: () => document.body } : {}) } className="forTest" - direction="down" + direction="up_down" refreshing={this.state.refreshing} onRefresh={() => { this.setState({ refreshing: true }); diff --git a/src/PropsType.ts b/src/PropsType.ts index f8e80d1..8dffc32 100644 --- a/src/PropsType.ts +++ b/src/PropsType.ts @@ -9,7 +9,7 @@ export interface Indicator { export interface PropsType { getScrollContainer: () => React.ReactNode; - direction: 'down' | 'up'; + direction: 'down' | 'up' | 'up_down'; refreshing?: boolean; distanceToRefresh: number; onRefresh: () => void; diff --git a/src/PullToRefresh.tsx b/src/PullToRefresh.tsx index b737cb1..7a953df 100644 --- a/src/PullToRefresh.tsx +++ b/src/PullToRefresh.tsx @@ -21,6 +21,7 @@ const isWebView = typeof navigator !== 'undefined' && /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent); const DOWN = 'down'; const UP = 'up'; +const UP_DOWN = 'up_down'; const INDICATOR = { activate: 'release', deactivate: 'pull', release: 'loading', finish: 'finish' }; export default class PullToRefresh extends React.Component { @@ -32,13 +33,6 @@ export default class PullToRefresh extends React.Component { indicator: INDICATOR as Indicator, } as PropsType; - // https://github.com/yiminghe/zscroller/blob/2d97973287135745818a0537712235a39a6a62a1/src/Scroller.js#L355 - // currSt: `activate` / `deactivate` / `release` / `finish` - state = { - currSt: '', - dragOnEdge: false, - }; - containerRef: any; contentRef: any; _to: any; @@ -46,9 +40,22 @@ export default class PullToRefresh extends React.Component { _startScreenY: any; _lastScreenY: any; _timer: any; + _direction: string; shouldUpdateChildren = false; + constructor(props: any) { + super(props); + const { direction } = props; + // https://github.com/yiminghe/zscroller/blob/2d97973287135745818a0537712235a39a6a62a1/src/Scroller.js#L355 + // currSt: `activate` / `deactivate` / `release` / `finish` + this.state = { + currSt: '', + dragOnEdge: false, + }; + this._direction = direction === UP_DOWN ? DOWN : direction; + } + shouldComponentUpdate(nextProps: any) { this.shouldUpdateChildren = this.props.children !== nextProps.children; return true; @@ -59,14 +66,14 @@ export default class PullToRefresh extends React.Component { return; } // triggerPullToRefresh 需要尽可能减少 setState 次数 - this.triggerPullToRefresh(); + this.triggerPullToRefresh(this._direction); } componentDidMount() { // `getScrollContainer` most likely return React.Node at the next tick. Need setTimeout setTimeout(() => { this.init(this.props.getScrollContainer() || this.containerRef); - this.triggerPullToRefresh(); + this.triggerPullToRefresh(this._direction); }); } @@ -75,15 +82,15 @@ export default class PullToRefresh extends React.Component { this.destroy(this.props.getScrollContainer() || this.containerRef); } - triggerPullToRefresh = () => { + triggerPullToRefresh = (direction: string) => { // 在初始化时、用代码 自动 触发 pullToRefresh // 注意:当 direction 为 up 时,当 visible length < content length 时、则看不到效果 if (!this.state.dragOnEdge) { if (this.props.refreshing) { - if (this.props.direction === UP) { + if (direction === UP) { this._lastScreenY = - this.props.distanceToRefresh - 1; } - if (this.props.direction === DOWN) { + if (direction === DOWN) { this._lastScreenY = this.props.distanceToRefresh + 1; } // change dom need after setState @@ -149,15 +156,19 @@ export default class PullToRefresh extends React.Component { onTouchMove = (ele: any, e: any) => { // 使用 pageY 对比有问题 const _screenY = e.touches[0].screenY; - const { direction } = this.props; - - // 拖动方向不符合的不处理 - if (direction === UP && this._startScreenY < _screenY || - direction === DOWN && this._startScreenY > _screenY) { - return; + if (this.props.direction === UP_DOWN) { + // if props.direction = up_down, auto detect direction when ontouchmove + this._direction = this._startScreenY > _screenY ? UP : DOWN; + } else { + // 拖动方向不符合的不处理 + this._direction = this.props.direction; + if (this._direction === UP && this._startScreenY < _screenY || + this._direction === DOWN && this._startScreenY > _screenY) { + return; + } } - if (this.isEdge(ele, direction)) { + if (this.isEdge(ele, this._direction)) { if (!this.state.dragOnEdge) { this.setState({ dragOnEdge: true }); } @@ -223,7 +234,7 @@ export default class PullToRefresh extends React.Component { render() { const { className, prefixCls, children, getScrollContainer, - direction, onRefresh, refreshing, indicator, distanceToRefresh, ...restProps, + onRefresh, refreshing, indicator, distanceToRefresh, ...restProps, } = this.props; const renderChildren = { return (
this.contentRef = el}> - {direction === UP ? renderChildren : null}
{(indicator as any)[this.state.currSt] || (INDICATOR as any)[this.state.currSt]}
- {direction === DOWN ? renderChildren : null} + {renderChildren}
); }; if (getScrollContainer()) { - return renderRefresh(`${prefixCls}-content ${prefixCls}-${direction}`); + return renderRefresh(`${prefixCls}-content ${prefixCls}-${this._direction}`); } return (
this.containerRef = el} - className={classNames(className, prefixCls, `${prefixCls}-${direction}`)} + className={classNames(className, prefixCls, `${prefixCls}-${this._direction}`)} {...restProps} > {renderRefresh(`${prefixCls}-content`)}