本文工作,涉及到以下几个知识点
- 请求网络并得到数据
- 创建Button并触发按钮事件测试网络
- 创建列表listview
- 创建CELL
- 根据返回的数据填充CELL
使用Fetch请求网络
React Native提供了和web标准一致的Fetch API,用于满足开发者访问网络的需求。如果你之前使用过XMLHttpRequest
(即俗称的ajax)或是其他的网络API,那么Fetch用起来将会相当容易上手。这篇文档只会列出Fetch的基本用法,并不会讲述太多细节,你可以使用你喜欢的搜索引擎去搜索fetch api
关键字以了解更多信息。
发起网络请求
要从任意地址获取内容的话,只需简单地将网址作为参数传递给fetch方法即可(fetch这个词本身也就是获取
的意思):
fetch('https://mywebsite.com/mydata.json')
Fetch还有可选的第二个参数,可以用来定制HTTP请求一些参数。你可以指定header参数,或是指定使用POST方法,又或是提交数据等等:
提供两个可用的url,返回json
http://facebook.github.io/react-native/movies.json
http://bbs.reactnative.cn/api/category/3
可以替换下面的url
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
TIPS:本人用的是xcode8做测试,遇到网络请求不通的情况,解决方法是在info.plist加入一项允许http的请求,这是由于兼容ios9+的一种方式,通过看控制台的log知道访问的结果.
查看测试结果也可以利用工具Charles
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</plist>
创建按钮并触发事件 TouchableHighlight
由于RN的特点,没有直接对Button封装出来,但是有可用的可点击组件,会相应点击事件。
中文网TouchableHightlight介绍
本组件用于封装视图,使其可以正确响应触摸操作。当按下的时候,封装的视图的不透明度会降低,同时会有一个底层的颜色透过而被用户看到,使得视图变暗或变亮。在底层实现上,实际会创建一个新的视图到视图层级中,如果使用的方法不正确,有时候会导致一些不希望出现的视觉效果。譬如没有给视图的backgroundColor显式声明一个不透明的颜色。
例子:
renderButton: function() {
return (
<TouchableHighlight onPress={this._onPressButton}>
<Image
style={styles.button}
source={require('./button.png')}
/>
</TouchableHighlight>
);
},
注意:TouchableHighlight只支持一个子节点
如果你希望包含多个子组件,用一个View来包装它们。
所以结合上面的网络请求,我们的按钮触发事件可以这样写
buttonTap=()=>{
fetch( 'http://bbs.reactnative.cn/api/category/3')
.then((response)=>response.json())
.then((jsondata) =>{
console.log(jsondata);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({dataSource: ds.cloneWithRows(jsondata.topics)});
this.setState({title:jsondata.description});
//alert(jsondata);
})
.catch((error)=>{
alert(error);
console.warning(error);
});
};
按钮的布局代码
render() {
return (
<View style={[styles.container,{paddingTop: 22}]}>
<TouchableHighlight style={{alignSelf:'flex-start'}} onPress={this.buttonTap} >
<Image
style={styles.button}
source={require('./img/favicon.png')}
/>
);
}
创建ListView
ListView
组件用于显示一个垂直的滚动列表,其中的元素之间结构近似而仅数据不同。
ListView
更适于长列表数据,且元素个数可以增删。和ScrollView
不同的是,ListView
并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。
ListView
组件必须的两个属性是dataSource
和renderRow
。dataSource
是列表的数据源,而renderRow
则逐个解析数据源中的数据,然后返回一个设定好格式的组件来渲染。
下面的例子创建了一个简单的ListView
,并预设了一些模拟数据。首先是初始化ListView
所需的dataSource
,其中的每一项(行)数据之后都在renderRow
中被渲染成了Text
组件,最后构成整个ListView
。
rowHasChanged
函数也是ListView
的必需属性。这里我们只是简单的比较两行数据是否是同一个数据(===符号只比较基本类型数据的值,和引用类型的地址)来判断某行数据是否变化了。
import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View } from 'react-native';
class ListViewBasics extends Component {
// 初始化模拟数据
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};
}
render() {
return (
<View style={{paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
</View>
);
}
}
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent('ListViewBasics', () => ListViewBasics);
以上介绍了一个简单的ListView
,然而现实中的CELL并没有如此简单,我们需要重构CELL的组织方式
创建展示的CELL
如果学过RN的布局方式,定制化CELL就是个简单的事情,此处需要用到alighitmes,justifycontent,具体的可以参考 React Native 的布局方式flextbox
直接给出代码
class CELL extends Component{
constructor(props){
super(props);
this.state = { detailTitle:'aaaa'};
}
render(){
return(
<View style={{flexDirection: 'column', backgroundColor:'#F5DD00'}}>
<View style={{flexDirection: 'row',padding:10, justifyContent:'center',flex:1,alignItems:'center'}} >
<Text style={{flex:2 ,marginLeft:10,marginRight:10,fontSize: 15}} >{this.props.title}</Text>
<Text style={{flex:1,marginRight:10,color:'gray',fontSize: 12,textAlign:'right'}}>{this.props.detailTitle}</Text>
</View>
<View style={{height:.5,alignSelf:'stretch',backgroundColor:'gray'}}></View>
</View>
);
}
}
要实现以上的需求,效果图如下
- 大伙可以先不看代码,自己组织代码试一下!
- 有问题欢迎在下面留言
- 不要吝啬自己的喜欢,有用的话点个赞吧
源代码如下:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
TextInput,
Image,
View,ScrollView,
ListView,
TouchableHighlight,
} from 'react-native';
class RNCSDemo extends Component {
// 初始化模拟数据
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
// 'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};
this.buttonTap();//初始化
}
getMoviesFromApiAsync() {
return fetch('http://facebook.github.io/react-native/movies.json',
{
headers:{
'Accept': 'application/json',
'Content-Type':'application/json',
}
})
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
}
buttonTap=()=>{
fetch( 'http://bbs.reactnative.cn/api/category/3'
// , {
// method: 'GET',
// headers: {
// 'Accept': 'application/json',
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify({
// } )
// }
).then((response)=>response.json())
.then((jsondata) =>{
console.log(jsondata);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({dataSource: ds.cloneWithRows(jsondata.topics)});
this.setState({title:jsondata.description});
//alert(jsondata);
})
.catch((error)=>{
alert(error);
console.warning(error);
});
};
render() {
return (
<View style={[styles.container,{paddingTop: 22}]}>
<TouchableHighlight style={{alignSelf:'flex-start'}} onPress={this.buttonTap} >
<Image
style={styles.button}
source={require('./img/favicon.png')}
/>
</TouchableHighlight>
<Text style={{textAlign:'center',alignSelf:'center'}} >{this.state.title}</Text>
<ListView style={{flex:5}}
dataSource={this.state.dataSource}
renderRow={(rowData) => <CELL title={rowData.title} detailTitle={rowData.timestampISO}></CELL>}
/>
</View>
);
}
}
class CELL extends Component{
constructor(props){
super(props);
this.state = { detailTitle:'aaaa'};
}
render(){
return(
<View style={{flexDirection: 'column', backgroundColor:'#F5DD00'}}>
<View style={{flexDirection: 'row',padding:10, justifyContent:'center',flex:1,alignItems:'center'}} >
<Text style={{flex:2 ,marginLeft:10,marginRight:10,fontSize: 15}} >{this.props.title}</Text>
<Text style={{flex:1,marginRight:10,color:'gray',fontSize: 12,textAlign:'right'}}>{this.props.detailTitle}</Text>
</View>
<View style={{height:.5,alignSelf:'stretch',backgroundColor:'gray'}}></View>
</View>
);
}
}
const styles= StyleSheet.create({
container:{flex:1,
justifyContent:'center',
backgroundColor: '#F5FC00',}
});
AppRegistry.registerComponent('RNCSDemo', () => RNCSDemo);