React Native 实例 - BBC新闻客户端

来源:互联网 发布:数据模型软件 编辑:程序博客网 时间:2024/05/17 00:59

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

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

BBC

主要技术

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

List


新闻详情

主要是解析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比较复杂, 不做过多介绍, 参考源码.

Detail


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

2 0
原创粉丝点击