欢迎Follow我的GitHub: https://github.com/SpikeKing
关于React Native
的实例,BBC新闻客户端. 通过访问BBC的公开网络接口,获取新闻内容,也可以根据类型显示. 在编写代码中,学习RN的知识,源码是使用ES6的规范编写,符合Facebook的RN代码最新规范.
主要技术
本文源码的GitHub下载地址
配置项目
初始化项目WclBBCNews,修改package.json
,添加依赖库.
Html解析库: htmlparser
,时间处理库: moment
,线性梯度库: react-native-linear-gradient
,视频库: react-native-video
.
"dependencies": {
"react": "^0.14.8","react-native": "^0.24.1","htmlparser": "^1.7.7","moment": "^2.11.1","react-native-linear-gradient": "^1.4.0","react-native-video": "^0.6.1" }
初始化主模块index.ios.js
,使用NavigatorIOS
导航页面,首页组件Feed模块.
render() {
return (
<NavigatorIOS style={{flex:1}} translucent={false} barTintColor={'#BB1919'} titleTextColor={'white'} tintColor={'white'} initialRoute={{ component: Feed,title: "Feed",passProps: {} }}/> ); }
渲染使用动态加载组件,StatusBar使用浅色样式.
_renderScene(route,navigator) {
var Component = route.component;
StatusBar.setBarStyle('light-content');
return (
<Component {...route.props} changeNavBarHeight={this.changeNavBarHeight} navigator={navigator} route={route}/> ); }
StatusBar样式只有两种,默认
default
,字是黑色; 可选light-content
,字是白色.
新闻列表
Feed页面,主要以列表形式,即ListView
标签,显示新闻. 未加载完成时,调用页面加载提示符ActivityIndicatorIOS
,显示动画.
render() {
// 未加载完成时,调用加载页面
if (!this.state.loaded) {
return this._renderLoading();
}
// ...
}
_renderLoading() {
return (
<View style={{flexDirection: 'row',justifyContent: 'center',flex: 1}}> <ActivityIndicatorIOS animating={this.state.isAnimating} style={{height: 80}} size="large"/> </View> ); }
加载完成后,调用ListView
显示页面,renderRow
渲染每一行,refreshControl
加载页面的过场.
return (
<ListView testID={"Feed Screen"} dataSource={this.state.dataSource} renderRow={this._renderStories.bind(this)} style={{backgroundColor: '#eee'}} contentInset={{top:0, left:0,bottom: 64,right: 0}} scrollEventThrottle={200} {...this.props} refreshControl={ <RefreshControl refreshing={this.state.isRefreshing} onRefresh={this._fetchData.bind(this)} tintColor='#BB1919' title="Loading..." progressBackgroundColor="#FFFF00" />} /> );
每一行使用Story
模块渲染.
_renderStories(story) {
return (
<Story story={story} navigator={this.props.navigator}/> ); }
componentDidMount() {
this._fetchData();
}
通过访问BBC的网络请求,异步获取数据. 使用_filterNews
过滤需要的数据,把数据设置入每一行,修改状态setState
,重新渲染页面.
_fetchData() {
this.setState({isRefreshing: true});
fetch(`http://trevor-producer-cdn.api.bbci.co.uk/content${this.props.collection || '/cps/news/world'}`)
.then((response) => response.json())
.then((responseData) => this._filterNews(responseData.relations))
.then((newItems) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newItems),loaded: true,isRefreshing: false,isAnimating: false
})
}).done();
}
列表项提供分类显示功能,点击类别,可以重新加载所选类型的新闻,把Feed
页面再次添加至导航navigator
,即页面栈.
_pressedCollection(collection) {
this.props.navigator.push({
component: Feed,title: collection.content.name,passProps: {
collection: collection.content.id,navigator: this.props.navigator
}
});
}
_pressedStory(story) {
this.props.navigator.push({
component: StoryDetail,title: this._truncateTitle(story.content.name),passProps: {story,navigator: this.props.navigator}
});
}
@H_213_403@新闻详情
主要是解析HTML页面,加载并显示,除了文字之外,会显示图片\视频\超链接等样式. 渲染使用动态元素,状态state
的elements
属性.
render() {
if (this.state.loading) {
return (
<Text>Loading</Text> ); } return this.state.elements; }
页面启动时,加载数据. 在_fetchStoryData
方法中,进行处理,使用回调返回数据. 主要内容body
与多媒体media
通过滚动视图ScrollView
的形式显示出来.
componentDidMount() {
this._fetchStoryData(
// media表示视频或图片.
(result,media) => {
const rootElement = result.find(item => {
return item.name === 'body';
});
XMLToReactMap.createReactElementsWithXMLRoot(rootElement,media)
.then(array => {
var scroll = React.createElement(ScrollView,{
contentInset: {top: 0,left: 0,bottom: 64,right: 0},style: {flex: 1,flexDirection: 'column',backgroundColor: 'white'},accessibilityLabel: "Story Detail"
},array);
this.setState({loading: false,elements: scroll});
});
}
);
}
处理数据,使用fetch
方法,分离视频与图片,还有页面,通过回调cb(callback)
的处理返回数据.
_fetchStoryData(cb) {
// 提取数据,转换JSON格式,图片过滤,视频过滤,组合relations,解析.
fetch(`http://trevor-producer-cdn.api.bbci.co.uk/content${this.props.story.content.id}`)
.then((response) => response.json())
.then((responseData) => {
const images = responseData.relations.filter(item => {
return item.primaryType === 'bbc.mobile.news.image';
});
const videos = responseData.relations.filter(item => {
return item.primaryType === 'bbc.mobile.news.video';
});
const relations = {images,videos};
this._parseXMLBody(responseData.body,(result) => {
cb(result,relations);
});
}).done();
}
使用Tautologistics
解析dom
数据与body
数据. DOM,即Document Object Model,文件对象模型.
_parseXMLBody(body,cb) {
var handler = new Tautologistics.NodeHtmlParser.DefaultHandler(
function (error,dom) {
cb(dom)
},{enforceEmptyTags: false,ignoreWhitespace: true});
var parser = new Tautologistics.NodeHtmlParser.Parser(handler);
parser.parseComplete(body);
}
XML解析类XMLToReactMap
比较复杂,不做过多介绍,参考源码.
感谢我的朋友Joel Trew的实例,本文改动一些源码.
通过编写新闻类应用,学习使用网络请求和解析HTML格式的文本. 多编码多思考,不断学习,React Native
是非常有意思的开发语言.
OK,that’s all! Enjoy it!
最初发布地址:
http://www.wangchenlong.org/2016/05/07/1605/071-rn-bbc-news/
欢迎Follow我的GitHub,关注我的简书,CSDN,掘金. 我已委托“维权骑士”为我的文章进行维权行动. 未经授权,禁止转载,授权或合作请留言.