微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

React Native 实例 - BBC新闻客户端

欢迎Follow我的GitHub: https://github.com/SpikeKing

关于React Native的实例,BBC新闻客户端. 通过访问BBC的公开网络接口,获取新闻内容,也可以根据类型显示. 在编写代码中,学习RN的知识,源码是使用ES6的规范编写,符合Facebook的RN代码最新规范.

主要技术

  1. 访问网络请求,过滤内容,获取数据.
  2. 显示多媒体页面,图片,视频,链接等.

本文源码的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" }

目前,React Native禁止使用-初始化项目名称,最好使用驼峰式.

初始化主模块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}/> ); }

启动页面的时候,使用fetch方法加载数据.

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
    }
  });
}

点击列表项,跳转至详情页面StoryDetail.

_pressedStory(story) {
  this.props.navigator.push({
    component: StoryDetail,title: this._truncateTitle(story.content.name),passprops: {story,navigator: this.props.navigator}
  });
}

新闻详情

主要是解析HTML页面,加载并显示,除了文字之外,会显示图片\视频\超链接等样式. 渲染使用动态元素,状态stateelements属性.

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,掘金. 我已委托“维权骑士”为我的文章进行维权行动. 未经授权,禁止转载,授权或合作请留言.

原文地址:https://www.jb51.cc/react/306764.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐