PullToRefresh 拉动刷新
通过触发,立刻重新加载内容。规则
可以和
ListView
结合使用,也可以单独使用。可考虑定期自动刷新, e.g. 登录 APP 后,自动刷新首页 List。
代码演示
import { PullToRefresh, Button } from 'antd-mobile';
function genData() {
const dataArr = [];
for (let i = 0; i < 20; i++) {
dataArr.push(i);
}
return dataArr;
}
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
refreshing: false,
down: true,
height: document.documentElement.clientHeight,
data: [],
};
}
componentDidMount() {
const hei = this.state.height - ReactDOM.findDOMNode(this.ptr).offsetTop;
setTimeout(() => this.setState({
height: hei,
data: genData(),
}), 0);
}
render() {
return (<div>
<Button
style={{ marginBottom: 15 }}
onClick={() => this.setState({ down: !this.state.down })}
>
direction: {this.state.down ? 'down' : 'up'}
</Button>
<PullToRefresh
damping={60}
ref={el => this.ptr = el}
style={{
height: this.state.height,
overflow: 'auto',
}}
indicator={this.state.down ? {} : { deactivate: '上拉可以刷新' }}
direction={this.state.down ? 'down' : 'up'}
refreshing={this.state.refreshing}
onRefresh={() => {
this.setState({ refreshing: true });
setTimeout(() => {
this.setState({ refreshing: false });
}, 1000);
}}
>
{this.state.data.map(i => (
<div key={i} style={{ textAlign: 'center', padding: 20 }}>
{this.state.down ? 'pull down' : 'pull up'} {i}
</div>
))}
</PullToRefresh>
</div>);
}
}
ReactDOM.render(<Demo />, mountNode);
/* eslint no-dupe-keys: 0, no-mixed-operators: 0 */
import { PullToRefresh, ListView, Button } from 'antd-mobile';
const data = [
{
img: 'https://zos.alipayobjects.com/rmsportal/dKbkpPXKfvZzWCM.png',
title: 'Meet hotel',
des: '不是所有的兼职汪都需要风吹日晒',
},
{
img: 'https://zos.alipayobjects.com/rmsportal/XmwCzSeJiqpkuMB.png',
title: 'McDonald\'s invites you',
des: '不是所有的兼职汪都需要风吹日晒',
},
{
img: 'https://zos.alipayobjects.com/rmsportal/hfVtzEhPzTUewPm.png',
title: 'Eat the week',
des: '不是所有的兼职汪都需要风吹日晒',
},
];
const NUM_ROWS = 20;
let pageIndex = 0;
function genData(pIndex = 0) {
const dataArr = [];
for (let i = 0; i < NUM_ROWS; i++) {
dataArr.push(`row - ${(pIndex * NUM_ROWS) + i}`);
}
return dataArr;
}
class App extends React.Component {
constructor(props) {
super(props);
const dataSource = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
});
this.state = {
dataSource,
refreshing: true,
isLoading: true,
height: document.documentElement.clientHeight,
useBodyScroll: false,
};
}
// If you use redux, the data maybe at props, you need use `componentWillReceiveProps`
// componentWillReceiveProps(nextProps) {
// if (nextProps.dataSource !== this.props.dataSource) {
// this.setState({
// dataSource: this.state.dataSource.cloneWithRows(nextProps.dataSource),
// });
// }
// }
componentDidUpdate() {
if (this.state.useBodyScroll) {
document.body.style.overflow = 'auto';
} else {
document.body.style.overflow = 'hidden';
}
}
componentDidMount() {
const hei = this.state.height - ReactDOM.findDOMNode(this.lv).offsetTop;
setTimeout(() => {
this.rData = genData();
this.setState({
dataSource: this.state.dataSource.cloneWithRows(genData()),
height: hei,
refreshing: false,
isLoading: false,
});
}, 1500);
}
onRefresh = () => {
this.setState({ refreshing: true, isLoading: true });
// simulate initial Ajax
setTimeout(() => {
this.rData = genData();
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.rData),
refreshing: false,
isLoading: false,
});
}, 600);
};
onEndReached = (event) => {
// load new data
// hasMore: from backend data, indicates whether it is the last page, here is false
if (this.state.isLoading && !this.state.hasMore) {
return;
}
console.log('reach end', event);
this.setState({ isLoading: true });
setTimeout(() => {
this.rData = [...this.rData, ...genData(++pageIndex)];
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.rData),
isLoading: false,
});
}, 1000);
};
render() {
const separator = (sectionID, rowID) => (
<div
key={`${sectionID}-${rowID}`}
style={{
backgroundColor: '#F5F5F9',
height: 8,
borderTop: '1px solid #ECECED',
borderBottom: '1px solid #ECECED',
}}
/>
);
let index = data.length - 1;
const row = (rowData, sectionID, rowID) => {
if (index < 0) {
index = data.length - 1;
}
const obj = data[index--];
return (
<div key={rowID}
style={{
padding: '0 15px',
backgroundColor: 'white',
}}
>
<div style={{ height: '50px', lineHeight: '50px', color: '#888', fontSize: '18px', borderBottom: '1px solid #ddd' }}>
{obj.title}
</div>
<div style={{ display: '-webkit-box', display: 'flex', padding: '15px' }}>
<img style={{ height: '63px', width: '63px', marginRight: '15px' }} src={obj.img} alt="" />
<div style={{ display: 'inline-block' }}>
<div style={{ marginBottom: '8px', color: '#000', fontSize: '16px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '250px' }}>{obj.des}-{rowData}</div>
<div style={{ fontSize: '16px' }}><span style={{ fontSize: '30px', color: '#FF6E27' }}>{rowID}</span> 元/任务</div>
</div>
</div>
</div>
);
};
return (<div>
<Button
style={{ margin: '30px 15px' }}
inline
onClick={() => this.setState({ useBodyScroll: !this.state.useBodyScroll })}
>
{this.state.useBodyScroll ? 'useBodyScroll' : 'partial scroll'}
</Button>
<ListView
key={this.state.useBodyScroll ? '0' : '1'}
ref={el => this.lv = el}
dataSource={this.state.dataSource}
renderHeader={() => <span>Pull to refresh</span>}
renderFooter={() => (<div style={{ padding: 30, textAlign: 'center' }}>
{this.state.isLoading ? 'Loading...' : 'Loaded'}
</div>)}
renderRow={row}
renderSeparator={separator}
useBodyScroll={this.state.useBodyScroll}
style={this.state.useBodyScroll ? {} : {
height: this.state.height,
border: '1px solid #ddd',
margin: '5px 0',
}}
pullToRefresh={<PullToRefresh
refreshing={this.state.refreshing}
onRefresh={this.onRefresh}
/>}
onEndReached={this.onEndReached}
pageSize={5}
/>
</div>);
}
}
ReactDOM.render(<App />, mountNode);
API
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
direction | 拉动方向,可以是 up 或 down | String | down |
distanceToRefresh | 刷新距离 | number | 25 |
refreshing | 是否显示刷新状态 | bool | false |
onRefresh | 必选, 刷新回调函数 | () => void | - |
indicator | 指示器配置 { activate: ReactNode, deactivate: ReactNode, release: ReactNode, finish: ReactNode } | Object | - |
damping | 拉动距离限制, 建议小于 200 | number | 100 |
distanceToRefresh = window.devicePixelRatio * 25