在本系列的第一部分中,您学习了如何在机器上设置React Native,如何创建和使用自定义组件以及如何使用第三方库(例如moment.js) 。 在本教程中,您将学习如何使用fetch
发出网络请求,如何使用内置的WebView
组件呈现网页以及如何在物理设备上运行该应用程序。
1.提取API包装器
在本系列的第一部分中,我们使用了api
函数,但尚未定义它。 首先创建一个src目录,并向其中添加一个文件api.js。 打开文件并添加以下内容:
module.exports = function(url){
return fetch(url).then(function(response){
return response.json();
}).then(function(json){
return json;
});
}
该文件使用fetch
功能,默认情况下,该功能在React Native中可用。 此功能允许该应用执行网络请求。 如果您使用过jQuery ,则它与$.ajax
函数非常相似。 您指定一个URL和一些可选数据,然后会返回响应。
唯一的区别是您需要做一些额外的工作。 捕获第一个promise的函数将返回原始响应,这意味着您必须在response
上调用json
方法以获得返回JSON字符串的promise。 因此,您必须从中返回结果,并通过再次调用then
函数来捕获promise, then
传递将在promise解析后将被调用的函数。
然后,JSON字符串将作为参数传递给此函数,因此我们只返回它。 fetch
方法返回一个promise,因此,当我们调用api
方法时,我们仍然必须调用then
方法来捕获实际响应,就像在本系列第一部分中所做的那样。
api(story_url).then(
(story) => {
...
}
);
2. WebPage
组件
WebPage
组件负责呈现网页。 它使用WebView
组件执行此操作。
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
WebView
} = React;
var Button = require('react-native-button');
var GiftedSpinner = require('react-native-gifted-spinner');
var _ = require('lodash');
var WebPage = React.createClass({
getInitialState: function() {
return {
isLoading: true
};
},
render: function(){
return (<View style={styles.container}>
<View style={styles.webview_header}>
<View style={styles.header_item}>
<Button style={styles.button} onPress={this.back}>Back</Button>
</View>
<View style={styles.header_item}>
<Text style={styles.page_title}>{this.truncate(this.state.pageTitle)}</Text>
</View>
<View style={[styles.header_item, styles.spinner]}>
{ this.state.isLoading && <GiftedSpinner /> }
</View>
</View>
<View style={styles.webview_body}>
<WebView
url={this.props.url}
onNavigationStateChange={this.onNavigationStateChange}
/>
</View>
</View>);
},
truncate: function(str){
return _.truncate(str, 20);
},
onNavigationStateChange: function(navState) {
if(!navState.loading){
this.setState({
isLoading: false,
pageTitle: navState.title
});
}
},
back: function(){
this.props.navigator.pop();
}
});
var styles = StyleSheet.create({
container: {
flex: 1
},
webview_header: {
paddingLeft: 10,
backgroundColor: '#FF6600',
flex: 1,
justifyContent: 'space-between',
flexDirection: 'row'
},
header_item: {
paddingLeft: 10,
paddingRight: 10,
justifyContent: 'center'
},
webview_body: {
flex: 9
},
button: {
textAlign: 'left',
color: '#FFF'
},
page_title: {
color: '#FFF'
},
spinner: {
alignItems: 'flex-end'
}
});
module.exports = WebPage;
首先,我们通过创建所需变量并要求将要使用的库来进行一些内部管理。
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
WebView
} = React;
var Button = require('react-native-button');
var GiftedSpinner = require('react-native-gifted-spinner');
var _ = require('lodash');
接下来,我们创建WebPage
组件。
var WebPage = React.createClass({
...
});
我们将isLoading
设置为true
作为默认状态。 此属性负责确定是否显示微调器。 默认情况下,微调框应可见以指示该页面正在加载。
getInitialState: function() {
return {
isLoading: true
};
},
接下来,我们渲染组件。 像新闻项组件一样,该组件也具有标题和正文。 页眉包含一个后退按钮,页面标题和一个微调框。
render: function(){
return (<View style={styles.container}>
<View style={styles.webview_header}>
<View style={styles.header_item}>
<Button style={styles.button} onPress={this.back}>Back</Button>
</View>
<View style={styles.header_item}>
<Text style={styles.page_title}>{this.truncate(this.state.pageTitle)}</Text>
</View>
<View style={[styles.header_item, styles.spinner]}>
{ this.state.isLoading && <GiftedSpinner /> }
</View>
</View>
<View style={styles.webview_body}>
<WebView
url={this.props.url}
onNavigationStateChange={this.onNavigationStateChange}
/>
</View>
</View>);
},
该主体包含WebView
组件。 WebView
组件具有url
和onNavigationStateChange
属性。 url
是先前从NewsItems
组件中的viewPage
函数传递的URL。 因此,当执行以下代码时:
this.props.navigator.push({name: 'web_page', url: url});
index.android.js中的renderScene
方法也将执行,并将URL传递给它:
renderScene: function(route, navigator) {
var Component = ROUTES[route.name];
return (
<Component route={route} navigator={navigator} url={route.url} />
);
},
这就是通过从this.props.url
提取URL来访问URL的this.props.url
。
让我们回到添加到WebView
组件的属性。 我们具有onNavigationStateChange
属性,该属性用于指定每当Web视图导航到新页面时要执行的函数。 该函数如下所示:
onNavigationStateChange: function(navState) {
if(!navState.loading){
this.setState({
isLoading: false,
pageTitle: navState.title
});
}
},
调用上述函数时,将navState
作为参数传递。 它包含有关Web视图当前状态的信息,例如页面标题以及当前是否正在加载。 这是更新状态的理想场所。 当页面不再加载时,我们将isLoading
设置为false
并为pageTitle
设置一个值。
接下来,我们具有back
功能,该功能使导航器返回上一页。 每当用户点击标题中的后退按钮时,都会调用此方法。
back: function(){
this.props.navigator.pop();
}
truncate
函数限制了传递给函数的内容的长度。 我们使用此功能来限制网页页面标题的文本。
truncate: function(str){
return _.truncate(str, 20);
},
样式表如下所示:
var styles = StyleSheet.create({
container: {
flex: 1
},
webview_header: {
paddingLeft: 10,
backgroundColor: '#FF6600',
flex: 1,
justifyContent: 'space-between',
flexDirection: 'row'
},
header_item: {
paddingLeft: 10,
paddingRight: 10,
justifyContent: 'center'
},
webview_body: {
flex: 9
},
button: {
textAlign: 'left',
color: '#FFF'
},
page_title: {
color: '#FFF'
},
spinner: {
alignItems: 'flex-end'
}
});
最后,将组件暴露给外界:
module.exports = WebPage;
3.运行应用程序
要运行该应用程序,您需要一个Android设备或一个模拟器。 如果要使用仿真器,建议使用Genymotion 。 您可以通过执行以下命令来运行该应用程序:
react-native run-android
此命令将安装并启动应用程序。 但是,如果尝试这样做,则会出现以下错误:
这是因为React Native希望React服务器可以在您的机器上运行。 每当您在文本编辑器中保存更改时,React服务器都会编译应用程序。 react-native run-android
命令仅用于运行应用程序,以测试和调试应用程序。 这就是为什么它依赖React服务器来实际编译应用程序。
要消除该错误,您需要运行react-native start
命令来启动服务器。 第一次运行会花费一些时间,但是到了要显示以下内容的部分:
<END> Building Dependency Graph (35135ms)
您可以在项目目录上打开一个新的终端窗口,并执行adb shell input keyevent 82
。 这将在设备或仿真器中打开开发人员菜单。 菜单打开后,选择dev settings,然后选择debug server host&port 。
这将打开提示,要求您输入计算机的IP地址和端口。 找出您计算机的内部IP地址,并将其与端口8081一起输入提示,该端口是运行React服务器的默认端口。 换句话说,如果您的IP地址是192.168.254.254 ,则输入192.168.254.254:8081 。
之后,返回开发人员菜单并选择reload JS 。 这会重新加载应用程序,以便它检测到正在运行的React服务器实例。 该应用程序应该如何正常工作。
如果要在iOS设备上进行测试,请按照React Native网站上的指南进行操作 。
4.后续步骤
我们使用React Native构建了一个非常简洁的新闻阅读器应用程序。 下一步是什么? 如果您想了解更多有关React Native的信息,请参考以下几点:
- 通过将应用分解为几个可重用的组件来改进代码。 首先查看重复的代码。 例如,在我们创建的应用程序中,我们复制了标题和其中的组件。 您可以做的是创建一个标题组件,该标题组件接受标题作为属性,然后在需要标题的每个页面上都需要它。
- 通过创建一个服务器来缓存来自Hacker News API的项目,从而缩短应用程序的响应时间。 这样一来,您仅可以执行一个包含所有新闻项的网络请求,而不必像本教程中那样执行多个网络请求。
- 生成签名的APK,以便您可以在Google Play上分发该应用。 对于iOS,您可以使用Xcode将应用分发到Apple的App Store。
- 浏览有关访问本机设备功能(例如camera)的 API的文档 。
- 在Github上查看Awesome React Native回购。 该仓库包含可用于React Native的组件,资源和工具的列表。
- 如果您想了解有关React Native的新闻,请订阅React Native Newsletter 。
结论
而已。 在本教程中,您学习了如何与React Native一起创建一个与Hacker News API对话的新闻阅读器应用程序。 如果您有任何疑问,请将其放在下面的评论中,我会尽力解答。 您可以在GitHub上找到本教程的源文件。 谢谢阅读。