你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
首页
热门
推荐
精选
登录
|
注册
React Native :加载新闻列表
立即下载
用AI写一个
该例子支持:好用才打赏哦
现在下载学习
发布时间:2018-05-18
30人
|
浏览:2968次
|
收藏
|
分享
技术:Object-C
运行环境:Xcode 8.0
概述
本例子售卖如何新闻列表的加载与联动,供大家参考学习,谢谢
详细
## 标签与内容页联动 上一节([React Native : 自定义视图](http://www.demodashi.com/demo/11686.html "React Native : 自定义视图"))做到了点击标签自动移动,还差跟下面的视图进行联动。 首先创建 `NewsList.js` : ```javascript import React from 'react' import { View, Text, ListView, Image, StyleSheet, Dimensions } from 'react-native' const {width, height} = Dimensions.get('window') export default class NewsList extends React.Component { render() { const {style} = this.props return (
) } } const styles = StyleSheet.create({ view: { flex: 1, backgroundColor:'red' } }) ``` 然后在 `Home.js` 引入,再加入 `ScrollView` ,现在 `Home.js` 的 `redner()` 是这样子的,这里加入的 `ScrollView` 我们在后文中称为 `NewsScrollView` ```javascript render() { return (
{ this._getNewsLists()}
) } ``` `_getNewsLists()` 方法: ```javascript _getNewsLists() { let lists = [] if (this.state.list) { for (let index in this.state.list) { let dic = this.state.list[index] lists.push(
) } } return lists } _getColor(color, index) { index ++ if (index == 7) { return color } color = color + '0123456789abcdef'[Math.floor(Math.random()*16)] return this._getColor(color, index) } ``` 根据返回的数据创建对应数量的视图,给随机颜色方便看效果。 先设置滑动 `NewsScrollView ` 让标签跟着移动。 我们把 `SegmentedView` 中 `items.push` 中的 `onPress` 方法的实现单独写到一个方法里,然后在这里调用: ```javascript _moveTo(index) { const { list } = this.props //获取到 传入的数组 this.state.selectItem && this.state.selectItem._unSelect() this.state.selectItem = this.refs[index] if (list.length > maxItem) { let meiosis = parseInt(maxItem / 2) this.refs.ScrollView.scrollTo({x: (index - meiosis < 0 ? 0 : index - meiosis > list.length - maxItem ? list.length - maxItem : index - meiosis ) * this.state.itemWidth, y: 0, animated: true}) } } ``` 这里会发现我们给 `this.state` 加了一个 `itemWidth` ,原来我们获取 `itemWidth` 是在 `_getItems()` 中计算的,但是在渲染的过程中无法调用 `setState()` ,我们把计算 `itemWidth` 的方法移动到 : ```javascript componentWillReceiveProps(props) { const { list } = props //获取到 传入的数组 if (!list || list.length == 0) return // 计算每个标签的宽度 let itemWidth = width / list.length if (list.length > maxItem) { itemWidth = width / maxItem } this.setState({ itemWidth }) } ``` `componentWillReceiveProps(props)` 方法会在属性更新后调用,参数 `props` 是新的属性。 现在运行会发现点击标签可以正常改变标签的状态,然而拖动 `NewsScrollView ` 只会让上一个选中的变为未选中,新的标签并没有变为选中,这是因为选中状态只在标签被点击的时候进行了设置,我们需要给 `Item` 添加一个选中的方法 : ```javascript _select() { this.setState({ isSelect: true }) } ``` 然后在 `_moveTo(index)` 进行调用: ```javascript this.state.selectItem && this.state.selectItem._unSelect() this.state.selectItem = this.refs[index] this.state.selectItem._select() ``` 现在运行滑动 `NewsScrollView ` 上面的 `SegmentedView` 可以正常运行了。 最后设置点击标签可以让 `NewsScrollView` 滑动到对应的位置,我们需要给 `SegmentedView` 加入一个回调函数,在标签被点击的时候调用返回点击的 `index` ```javascript
{ this.refs.ScrollView.scrollTo({x: width * index, y: 0, animated: true}) }} /> ``` 在 `SegmentedView ` 进行调用: ```javascript _getItems() { const { list, selectItem } = this.props //获取到 传入的数组 if (!list || list.length == 0) return [] let items = [] for (let index in list) { let dic = list[index] items.push(
{ this._moveTo(index) selectItem && selectItem(index) }} /> ) } return items } ``` ### 加载新闻列表第一页数据 加载新闻列表第一页数据 在 `Home.js` 中已经给 `NewsList` 传入了数据,我们再给传入一个参数识别是否是第一页,初始只加载第一页的数据,也方便调试: ```javascript _getNewsLists() { let lists = [] if (this.state.list) { for (let index in this.state.list) { let dic = this.state.list[index] lists.push(
) } } return lists } ``` 然后去 `NewsList.js` 进行请求数据: ```javascript // 构造 constructor(props) { super(props); // 初始状态 this.state = { page: 1, rn: 1, }; } componentDidMount() { if (!this.props.isRequest) return this._onRefresh() } _onRefresh(page) { if (this.props.dic) { let url = 'http://api.iapple123.com/newspush/list/index.html?clientid=1114283782&v=1.1&type=' + this.props.dic.NameEN + '&startkey=&newkey=&index=' + (page ? page : this.state.page) + '&size=20&ime=6271F554-7B2F-45DE-887E-4A336F64DEE6&apptypeid=ZJZYIOS1114283782&rn=' + this.state.rn LOG('url=》', url) fetch(url, { method: 'GET', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, }) .then((res) => { res.json() .then((json) => { LOG('GET SUCCESSED then =>', url, json) }) }) .catch((e) => { LOG('GET ERROR then =>', url, e) }) }) .catch((error) => { LOG('GET ERROR=>', url, '==>', error) }) } } ``` 请求到数据后我们需要用 `ListView` ([官方文档](http://reactnative.cn/docs/0.43/listview.html#content)) 来显示, 所以导入 `ListView` ,然后去 `render()` 加入: ```javascript render() { const {style} = this.props return (
) } ``` 然后加入 `dataSource` 和 `renderRow`: ```javascript // 构造 constructor(props) { super(props); var getRowData = (dataBlob, sectionID, rowID) => { return dataBlob[sectionID][rowID] }; // 初始状态 this.state = { page: 1, rn: 1, dataSource: new ListView.DataSource({ getRowData: getRowData, rowHasChanged: (r1, r2) => r1 !== r2, }), }; this.renderRow = this.renderRow.bind(this) } renderRow(rowData, rowID, highlightRow) { return (
) } ``` ### 运行效果 我们要做的界面是这个样子  从上图可以看出来新闻分为 3 种样式,轮播图、有一张图片的和二、三张图片的。 接下来开始解析数据,解析完 `json` 数据发现只有一个数组,轮播图是取了前四个,剩下的根据 `ImagesList` 里图片的个数来判断, 去 `.then((json) => {` 加入 ```javascript let list = json.NewsList let swipers = [] let news = [] for (let index in list) { let dic = list[index] index < 4 ? swipers.push(dic) : news.push(dic) } news.splice(0, 0, swipers) this.setState({ dataSource: this.state.dataSource.cloneWithRows(news) }) ``` 现在 `news` 的数据结构为: ```javascript [ [ {}, {} ], {}, {} } ``` 然后去 `renderRow` 处理数据 如果是数组,那么返回轮播图: ```javascript if (Object.prototype.toString.call(rowData) === '[object Array]') { return (
) } ``` 这里的轮播图本来用的 [`Swiper`](https://github.com/leecade/react-native-swiper),但是在 `Android` 上有很多 BUG,我只好自己写了一个,但是在 `Android` 上的体验差强人意,源码在[这里](https://github.com/qiangxinyu/ReactNativeExample/blob/master/ReactNative4/App/Home/CarousePicture.js),把文件导入项目即可。 具体的可以看[这里](http://jiasm.org/2017/02/18/React-native%E8%B8%A9%E5%9D%91%E5%B0%8F%E8%AE%B0/) `touchIn` 是由于在 `Andoird` 上两个 `ScrollView` 重叠时,处于顶部的 `ScrollView` 滑动事件不会响应,因为底部的 `ScrollView` 进行了响应并拦截了事件,我们需要在手指接触到轮播图的时候禁用底部 `ScrollView` 的滑动属性,再手指离开的时候再进行恢复,所以还需要去 `Home.js` 加入: ```javascript _getNewsLists() { let lists = [] if (this.state.list) { for (let index in this.state.list) { let dic = this.state.list[index] lists.push(
{ this.refs.ScrollView.setNativeProps({scrollEnabled: !scrollEnabled}) }} /> ) } } return lists } ``` 然后根据 `ImagesList` 的个数来区分: ```javascript let imagesList = rowData.ImagesList if (imagesList && imagesList.length == 1) { return (
{rowData.Title}
{rowData.Source}
{rowData.PublishTime}
) } let images = [] for (let index in imagesList) { let dic = imagesList[index] images.push(
) } return (
{rowData.Title}
{images}
{rowData.Source}
{rowData.PublishTime}
) ``` 我这里的 `style` 没有进行整理,所以看着比较乱,正式开发中应该整理到 `styles` 里,看起来就简洁多了。 现在运行就可以显示第一页的数据了。 ### 项目结构 >项目结构如下: 
本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
感谢
0
手机上随时阅读、收藏该文章 ?请扫下方二维码
相似例子推荐
评论
作者
强新宇
4
例子数量
76
帮助
3
感谢
评分详细
可运行:
4.5
分
代码质量:
4.5
分
文章描述详细:
4.5
分
代码注释:
4.5
分
综合:
4.5
分
作者例子
使用AVPlayer制作一个播放器
React Native : 自定义视图
React Native :加载新闻列表
UICollectionViews有了简单的重排功能