如何使用 JavaScript 和 React Native 构建新闻应用程序
新闻API
新闻.js
App.js
文章.js
构建应用程序的要求:
- 对 JavaScript 语言有基本的了解。
- Node.js和react native。
- 使用的库:moment、react-native、react-native-elements。
如果您不熟悉这些资源,请不要担心——它们非常容易使用。
我们将在文章中讨论的主题是:
- 新闻API
- 获取 API
- 平面列表
- 下拉刷新
- 链接
还有更多……那就开始吧!你可以在这里
找到完整的项目仓库。
新闻API
一个简单易用的 API,可返回目前网络上实时更新的标题和文章的 JSON 元数据。— NewsAPI.org
首先,您应该继续注册 News Api 以获取免费的 apiKey(您的身份验证密钥)。
创建一个新的 React Native 项目,并为其命名news_app
(或任何你想要的名称)。在项目目录中,新建一个文件夹并将其命名为。在src
src 文件夹中,创建一个名为 news.js 的新文件。在这个文件中,我们将从 News API 获取包含标题的 JSON。src
components
新闻.js
const url =
"https://newsapi.org/v2/top-headlines?country=us&apiKey=YOUR_API_KEY_HERE";
export async function getNews() {
let result = await fetch(url).then(response => response.json());
return result.articles;
}
请务必YOUR_API_KEY_HERE
使用您自己的 API 密钥进行替换。有关新闻 API 的更多信息,请参阅newsapi 文档。
现在我们声明一个getNews
函数,它将为我们获取文章。导出该函数,以便我们可以在App.js
文件中使用它。
App.js
import React from 'react';
import { FlatList } from 'react-native';
// Import getNews function from news.js
import { getNews } from './src/news';
// We'll get to this one later
import Article from './src/components/Article';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { articles: [], refreshing: true };
this.fetchNews = this.fetchNews.bind(this);
}
// Called after a component is mounted
componentDidMount() {
this.fetchNews();
}
fetchNews() {
getNews()
.then(articles => this.setState({ articles, refreshing: false }))
.catch(() => this.setState({ refreshing: false }));
}
handleRefresh() {
this.setState(
{
refreshing: true
},
() => this.fetchNews()
);
}
render() {
return (
<FlatList
data={this.state.articles}
renderItem={({ item }) => <Article article={item} />}
keyExtractor={item => item.url}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh.bind(this)}
/>
);
}
}
在构造函数中,我们定义了初始状态。articles
它将在我们获取文章后存储它们,并refreshing
帮助我们刷新动画。请注意,我设置为refreshing
,true
因为当我们启动应用程序时,我们希望动画在加载文章时启动。componentDidMount
在组件挂载后立即调用。在其中我们调用fetchNews
方法。
componentDidMount() {
this.fetchNews();
}
fetchNews
我们调用该getNews()
方法会返回一个 Promise。因此,我们使用.then()
一个接受回调函数的方法,而回调函数又接受一个参数(即文章)。
现在将状态中的文章赋值给articles参数。我之所以只输入了articles
{articles:articles} ,是因为这是新的 ES6 语法,意思是 {articles:articles} ,然后我们设置refreshing
为false
来停止旋转动画。
fetchNews() {
getNews().then(
articles => this.setState({ articles, refreshing: false })
).catch(() => this.setState({ refreshing: false }));
}
.catch()
在被驳回的案件中被称为。
handleRefresh
启动旋转动画并调用fetchNews()
。我们传递() => this.fetchNews()
,因此在分配状态后会立即调用它。
handleRefresh() {
this.setState({ refreshing: true },() => this.fetchNews());
}
在该render
方法中,我们返回一个FlatList
元素。然后我们传递一些 props。data
是来自 的文章数组this.state
。 它renderItem
接受一个函数来渲染数组中的每个项目,但在我们的例子中,它只返回Article
我们之前导入的组件(我们稍后会讲到)。我们将该article
项目作为 prop 传递,以便稍后在该组件中使用。
文章.js
创建src/components
一个新的 JavaScript 文件并调用它Article.js
。
让我们首先使用 npm: 安装两个简单的库react-native-elements
,这为我们提供了一些可以使用的预制组件,并且moment
可以节省我们的时间。
使用终端/cmd 运行:
npm install --save react-native-elements moment
在 Article.js 中:
import React from 'react';
import { View, Linking, TouchableNativeFeedback } from 'react-native';
import { Text, Button, Card, Divider } from 'react-native-elements';
import moment from 'moment';
export default class Article extends React.Component {
render() {
const {
title,
description,
publishedAt,
source,
urlToImage,
url
} = this.props.article;
const { noteStyle, featuredTitleStyle } = styles;
const time = moment(publishedAt || moment.now()).fromNow();
const defaultImg =
'https://wallpaper.wiki/wp-content/uploads/2017/04/wallpaper.wiki-Images-HD-Diamond-Pattern-PIC-WPB009691.jpg';
return (
<TouchableNativeFeedback
useForeground
onPress={() => Linking.openURL(url)}
>
<Card
featuredTitle={title}
featuredTitleStyle={featuredTitleStyle}
image={{
uri: urlToImage || defaultImg
}}
>
<Text style={{ marginBottom: 10 }}>
{description || 'Read More..'}
</Text>
<Divider style={{ backgroundColor: '#dfe6e9' }} />
<View
style={{ flexDirection: 'row', justifyContent: 'space-between' }}
>
<Text style={noteStyle}>{source.name.toUpperCase()}</Text>
<Text style={noteStyle}>{time}</Text>
</View>
</Card>
</TouchableNativeFeedback>
);
}
}
const styles = {
noteStyle: {
margin: 5,
fontStyle: 'italic',
color: '#b2bec3',
fontSize: 10
},
featuredTitleStyle: {
marginHorizontal: 5,
textShadowColor: '#00000f',
textShadowOffset: { width: 3, height: 3 },
textShadowRadius: 3
}
};
这里有很多事情要做。首先,我们先解构proparticle
和styles
类下定义的对象。
我们render
定义time
来存储文章的发布时间。我们使用moment
库将日期转换为发布时间之后的时间,如果,则将publishedAt
或 从现在开始的时间转换为。publishedAt
null
defaultImg
被分配一个图像URL,以防文章图像的URL是null
。
该render
方法返回TouchableNativeFeedback
(TouchableOpacity
如果在您的平台上无法使用,请使用该方法)用于处理用户按下卡片时的操作。我们向其传递了一些 props:useForground
它告诉元素在卡片上显示涟漪效果时使用前景,以及onPress
,它接受一个函数并在用户按下卡片时执行该函数。我们传递() => Linking.openUrl(url)
的 仅仅是在用户按下卡片时打开完整文章的 URL。
这张卡片需要三个 props:featuredTitle
一个漂亮的标题,放在图片上方(title
如果需要,也可以用其他标题代替)featuredTitleStyle
,一个是 image,用于设置图片的样式;另一个是 image,它是来自 article props 的文章图片。否则,如果是null
,则使用defaultImg
。
..
featuredTitle={title}
featuredTitleStyle={featuredTitleStyle}
image={{ uri: urlToImage || defaultImg }}
..
至于text
元素,它将保存文章的描述。
<Text style={{ marginBottom: 10 }}>{description}</Text>
我们添加了一个divider
来将描述与时间和源名称分开。
<Divider style={{ backgroundColor: '#dfe6e9' }} />
在 下方Divider
,我们有一个View
包含来源名称和文章发布时间的。
..
<View
style={{ flexDirection: ‘row’, justifyContent: ‘space-between’ }} >
<Text style={noteStyle}>{source.name.toUpperCase()}</Text>
<Text style={noteStyle}>{time}</Text>
</View>
..
之后class
,我们定义了这些组件的样式。
现在,如果我们运行该应用程序:我们可以刷新应用程序 。好了!该应用程序的源代码可以在 GitHub 上找到,您可以对其进行改进并发出拉取请求😄。
希望你喜欢我的文章!如果你有任何疑问,欢迎评论或在推特上联系我,我一定会提供帮助 :)
也别忘了分享这篇文章😄👇。
文章来源:https://dev.to/msal/how-to-build-a-news-app-with-react-native-4ifd