1.下拉刷新 使用第三方插件
下载插件:
$ npm install react-native-pull@latest --save
引入:
import {PullList} from 'react-native-pull';
将 ListView 改为 PullList 即可
GDHalfHourHot.js
/** * 近半小时热门 */ import React, { Component } from 'react'; import { StyleSheet, Text, View, TouchableOpacity, Image, ListView, Dimensions, DeviceEventEmitter, } from 'react-native'; // 获取屏幕宽高 const {width, height} = Dimensions.get('window'); // 引入自定义导航栏组件 import CommunalNavBar from '../main/GDCommunalNavBar'; // 引入 cell import CommunalHotCell from '../main/GDCommunalHotCell'; // 引入 空白页组件 import NoDataView from '../main/GDNoDataView'; // 引入 下拉刷新组件 import {PullList} from 'react-native-pull'; export default class GDHalfHourHot extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { dataSource: new ListView.DataSource({rowHasChanged:(r1, r2) => r1 !== r2}), // 数据源 优化 loaded: false, // 用于判断是否显示空白页 }; // 绑定 this.fetchData = this.fetchData.bind(this); } // 网络请求 fetchData(resolve) { // 测试没用数据的情况 setTimeout(() => { fetch('http://guangdiu.com/api/gethots.php') // 请求地址 .then((response) => response.json()) // 定义名称 将数据转为json格式 .then((responseData) => { // 处理数据 // 修改dataSource的值 this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.data), loaded:true, }); // 关闭下来刷新动画 if (resolve !== undefined) { // 使用定时器 延时关闭动画 setTimeout(() => { resolve(); },1000); } }) .done(); // 结束 },3000) } // 跳回首页 popToHome() { this.props.navigator.pop(); } // 返回中间按钮 renderTitleItem() { return( <Text style={styles.navbarTitleItemStyle}>近半小时热门</Text> ); } // 返回右边按钮 renderRightItem() { return( <TouchableOpacity onPress={() => {this.popToHome()}} > <Text style={styles.navbarRightItemStyle}>关闭</Text> </TouchableOpacity> ); } // 判断显示列表 还是 显示空白页 renderListView() { if(this.state.loaded === false) { // 显示空白页 return( <NoDataView /> ); }else{ return( <PullList // 将ListView 改为 PullList // 下拉刷新 onPullRelease={(resolve) => this.fetchData(resolve)} // 数据源 通过判断dataSource是否有变化,来判断是否要重新渲染 dataSource={this.state.dataSource} renderRow={this.renderRow} // 隐藏水平线 showsHorizontalScrollIndicator={false} style={styles.listViewStyle} initialListSize={5} // 返回 listView 头部 renderHeader={this.renderHeader} /> ); } } // 返回 listView 头部 renderHeader() { return( <View style={styles.headerPromptStyle}> <Text>根据每条折扣的点击进行统计,每5分钟更新一次</Text> </View> ); } // 返回每一行cell的样式 renderRow(rowData) { // 使用cell组件 return( <CommunalHotCell image={rowData.image} title={rowData.title} /> ); } componentWillMount() { // 向GDMain.js 发送通知 隐藏tabBar DeviceEventEmitter.emit('isHiddenTabBar', true); } componentWillUnmount() { // 向GDMain.js 发送通知 显示tabBar DeviceEventEmitter.emit('isHiddenTabBar', false); } // 生命周期 组件渲染完成 已经出现在dom文档里 componentDidMount() { // 请求数据 this.fetchData(); } render() { return ( <View style={styles.container}> {/* 导航栏样式 */} <CommunalNavBar titleItem = {() => this.renderTitleItem()} rightItem = {() => this.renderRightItem()} /> {/* 根据网络状态决定是否渲染 listView */} {this.renderListView()} </View> ); } } const styles = StyleSheet.create({ container: { flex:1, alignItems: 'center', }, navbarTitleItemStyle: { fontSize:17, color:'black', marginLeft:50 }, navbarRightItemStyle: { fontSize:17, color:'rgba(123,178,114,1.0)', marginRight:15 }, headerPromptStyle: { height:44, width, backgroundColor:'rgba(239,239,239,0.5)', justifyContent:'center', alignItems:'center' }, listViewStyle: { width, } });
效果图:
2.POST 带参数请求
// 网络请求 fetchData(resolve) { // 初始化 formData let formData = new FormData(); // 添加参数 formData.append("count","5"); formData.append("mall","京东商城"); // 测试没用数据的情况 setTimeout(() => { fetch('http://guangdiu.com/api/getlist.php', { // url 请求网址 method: 'POST', // 请求方式 headers:{}, // 设置请求头(默认为空对象) body:formData, // 将formData传给body }) .then((response) => response.json()) // 定义名称 将数据转为json格式 .then((responseData) => { // 处理数据 // 修改dataSource的值 this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.data), loaded:true, }); // 关闭下来刷新动画 if (resolve !== undefined) { // 使用定时器 延时关闭动画 setTimeout(() => { resolve(); },1000); } }) .done(); // 结束 }); }
3.navigator 跳转动画 关闭 Navigator 返回手势
有时候我们需要在跳转的时候使用不同的跳转动画,比如我们 半小时热门 的跳转方式在 iOS 内叫 模态跳转,特性就是当页面退出后会直接销毁,多用于注册、登录等不需要常驻内存的界面。
react-native 中为了方便实现这样的功能,我们可以在初始化 Navigator 的时候,在 ‘configsSence’ 中进行操作;具体操作如下:
// 设置Navigator跳转动画 setNavAnimationType(route) { if(route.animationType) { // 外部有值传入 // 关闭返回手势 let conf = route.animationType; conf.gestures = null; return conf; }else{ // 默认动画 return Navigator.SceneConfigs.PushFromRight; } }
<Navigator // 设置路由 initialRoute = { { name: selectedTab, component: component } } // 设置导航动画 configureScene={(route) => this.setNavAnimationType(route)} renderScene = { (route, navigator) => { let Component = route.component; return <Component {...route.params} navigator={navigator} /> } } />
这样我们在需要跳转的地方只需要传入相应的参数即可。
// 跳转到近半小时热门 pushToHalfHourHot() { // this.props 可以获取所有组件属性 this.props.navigator.push({ component: HalfHourHot, // 设置调整动画 animationType: Navigator.SceneConfigs.FloatFromBottom, }) }
4.上拉加载更多
react-native-pull 框架的上拉加载使用也很简单,配合 onEndReached、onEndReachedThreshold、renderFooter使用
GDHome.js
/** * 首页 */ import React, { Component } from 'react'; import { StyleSheet, Text, View, TouchableOpacity, Image, ListView, Dimensions, ActivityIndicator, } from 'react-native'; // 引入 下拉刷新组件 import {PullList} from 'react-native-pull'; // 导航器 import CustomerComponents, { Navigator } from 'react-native-deprecated-custom-components'; // 获取屏幕宽高 const {width, height} = Dimensions.get('window'); // 引入自定义导航栏组件 import CommunalNavBar from '../main/GDCommunalNavBar'; // 引入 近半小时热门组件 import HalfHourHot from './GDHalfHourHot'; // 引入 搜索页面组件 import Search from './GDSearch'; // 引入 cell import CommunalHotCell from '../main/GDCommunalHotCell'; // 引入 空白页组件 import NoDataView from '../main/GDNoDataView'; export default class GDHome extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { dataSource: new ListView.DataSource({rowHasChanged:(r1, r2) => r1 !== r2}), // 数据源 优化 loaded: false, // 用于判断是否显示空白页 }; // 绑定 this.fetchData = this.fetchData.bind(this); this.loadMore = this.loadMore.bind(this); } // 网络请求 fetchData(resolve) { // 初始化 formData let formData = new FormData(); // 添加参数 formData.append("count","5"); formData.append("mall","京东商城"); // 测试没用数据的情况 setTimeout(() => { fetch('http://guangdiu.com/api/getlist.php', { // url 请求网址 method: 'POST', // 请求方式 headers:{}, // 设置请求头(默认为空对象) body:formData, // 将formData传给body }) .then((response) => response.json()) // 定义名称 将数据转为json格式 .then((responseData) => { // 处理数据 // 修改dataSource的值 this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.data), loaded:true, }); // 关闭下来刷新动画 if (resolve !== undefined) { // 使用定时器 延时关闭动画 setTimeout(() => { resolve(); },1000); } }) .done(); // 结束 }); } // 跳转到近半小时热门 pushToHalfHourHot() { // this.props 可以获取所有组件属性 this.props.navigator.push({ component: HalfHourHot, // 设置调整动画 animationType: Navigator.SceneConfigs.FloatFromBottom, }) } // 跳转到搜索页面 pushToSearch() { this.props.navigator.push({ component: Search, }) } // 返回左边按钮 renderLeftItem() { // 将组件返回出去 return( <TouchableOpacity onPress={() => {this.pushToHalfHourHot()}} > <Image source={{uri:'hot_icon_20x20'}} style={styles.navbarLeftItemStyle} /> </TouchableOpacity> ); } // 返回中间按钮 renderTitleItem() { return( <TouchableOpacity> <Image source={{uri:'navtitle_home_down_66x20'}} style={styles.navbarTitleItemStyle} /> </TouchableOpacity> ); } // 返回右边按钮 renderRightItem() { return( <TouchableOpacity // 跳转搜索页面 onPress={() => {this.pushToSearch()}} > <Image source={{uri:'search_icon_20x20'}} style={styles.navbarRightItemStyle} /> </TouchableOpacity> ); } // 加载更多 loadMore() { fetch('http://guangdiu.com/api/gethots.php') // 请求地址 .then((response) => response.json()) // 定义名称 将数据转为json格式 .then((responseData) => { // 处理数据 // 修改dataSource的值 this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.data), loaded:true, }); }) .done(); // 结束 } renderFooter() { return ( <View style={{height: 100}}> <ActivityIndicator /> </View> ); } // 根据网络状态决定是否渲染 listView renderListView() { if(this.state.loaded === false) { // 显示空白页 return( <NoDataView /> ); }else{ return( <PullList // 将ListView 改为 PullList // 下拉刷新 onPullRelease={(resolve) => this.fetchData(resolve)} // 数据源 通过判断dataSource是否有变化,来判断是否要重新渲染 dataSource={this.state.dataSource} renderRow={this.renderRow} // 隐藏水平线 showsHorizontalScrollIndicator={false} style={styles.listViewStyle} initialListSize={5} // 返回 listView 头部 renderHeader={this.renderHeader} // 上拉加载更多 onEndReached={this.loadMore} onEndReachedThreshold={60} renderFooter={this.renderFooter} /> ); } } // 返回每一行cell的样式 renderRow(rowData) { // 使用cell组件 return( <CommunalHotCell image={rowData.image} title={rowData.title} /> ); } // 生命周期 组件渲染完成 已经出现在dom文档里 componentDidMount() { // 请求数据 this.fetchData(); } render() { return ( <View style={styles.container}> {/* 导航栏样式 */} <CommunalNavBar leftItem = {() => this.renderLeftItem()} titleItem = {() => this.renderTitleItem()} rightItem = {() => this.renderRightItem()} /> {/* 根据网络状态决定是否渲染 listView */} {this.renderListView()} </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', }, navbarLeftItemStyle: { 20, height:20, marginLeft:15, }, navbarTitleItemStyle: { 66, height:20, }, navbarRightItemStyle: { 20, height:20, marginRight:15, }, listViewStyle: { width, }, });