这回我们使用远程数据,使用真正的数据结构,来实战一下。
首先,需要获取远程数据,我们创建一个方法_loadcatsandproject()来获取远程数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//从网络获取全部标签 _loadcatsandproject() { return fetch('https://XXXXXXXXXX/wechat/cat', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ }) }) .then((response) => response.json()) .then((responseJson) => { console.log('将获取到的分类给state'); this.setState({ categorys: responseJson.category, }) return responseJson.category; }) .catch((error) => { console.error(error); }) ; } |
首先我们使用fetch来获取网络数据,得到分类的json数据,并将数据赋值给state:
1 2 3 |
this.setState({ categorys: responseJson.category, }) |
描述一下服务器传来的分类json的结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
categories: [ { "id": "0", "name": "全部", }, { "id": "1", "name": "纯露", }, { "id": "2", "name": "参", } ] |
下面我们在构造函数中,调用这个方法,别忘了初始化state 的 categorys
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//轮播图片加 constructor(props) { ....... //从网络获取标签 this._loadcatsandproject(); //end 从网络获取标签 this.state = { dataSource: dataSource.cloneWithPages(BANNER_IMGS), catid: "全部", //修改网络 categorys: [], } } |
顺便在构造函数中修改一下state的catid以便点击分类:下划线的切换。
现在来到render()下,看看原来我们如何渲染:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<ScrollView showsHorizontalScrollIndicator={false} horizontal={true} > <View style={styles.active}> <Text style={styles.typebox} onPress={() => this._loadProduct('全部')}>全部</Text> </View> <View> <Text style={styles.typebox} onPress={() => this._loadProduct('分类1')} >分类1</Text> </View> <View > <Text style={styles.typebox} onPress={() => this._loadProduct('分类2')}>分类2</Text> </View> <View > <Text style={styles.typebox} onPress={() => this._loadProduct('分类3')}>分类3</Text> </View> <View > <Text style={styles.typebox} onPress={() => this._loadProduct('分类4')}>分类4</Text> </View> <View > <Text style={styles.typebox} onPress={() => this._loadProduct('分类5')}>分类5</Text> </View> <View > <Text style={styles.typebox} onPress={() => this._loadProduct('分类6')}>分类6</Text> </View> </ScrollView> |
但现在情况变了,我们需要动态循环出这些数据,我们改写这些代码如下:
1 2 3 4 5 |
<ScrollView showsHorizontalScrollIndicator={false} horizontal={true} > <View style={"全部"==this.state.catid?styles.active:""}><Text style={styles.typebox} onPress={() => this._loadProduct('全部')}> 全部</Text></View> {this._rendercatList(this.state.categorys)} </ScrollView> |
先看看这段代码:
1 2 |
<View style={"全部"==this.state.catid?styles.active:""}><Text style={styles.typebox} onPress={() => this._loadProduct('全部')}> 全部</Text></View> |
上面这段代码,因为全部标签,不用从网络获取,所以还是直接输出在视图中。
{“全部”==this.state.catid?styles.active:””}: 是负责点击后,下划线点亮的。
1 |
{this._rendercatList(this.state.categorys)} |
这个函数我们下面会创建它,他是用来输出,网络获取的分类的,传入的参数就是我们刚刚获取的分类对象:
1 2 3 4 |
_rendercatList(list) { console.log("进入模板map"); return list.map(item => this._itemcat(item)); } |
我们使用map将其循环输出,并_itemcat中构建每个分类的视图组件:
1 2 3 4 5 6 7 8 |
_itemcat(item) { console.log("输出每个标签模板"); return ( <View key={item.id} style={item.id==this.state.catid?styles.active:"" } ><Text key={item.id} style={styles.typebox} onPress={() => this._loadProduct(item.id)}> {item.name}</Text></View> ); } |
好了,这样我们就从网络中获取了,所有的分类并显示出来。
看看效果吧:
这里我粘贴了,这个HomeScreen.js的所有代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
import React, { Component } from 'react'; import { StyleSheet, Text, View, Image, //分类 ScrollView, //end 分类 //轮播图片加 Dimensions, //end 轮播图片加 } from 'react-native'; //轮播图片加 import ViewPager from 'react-native-viewpager'; var deviceWidth = Dimensions.get('window').width; //计算设备宽度 //end 轮播图片加 import { StackNavigator, } from 'react-navigation'; import { ItemScreen } from './ItemScreen'; //轮播图片加 const BANNER_IMGS = [ 'http://ac-c6scxa78.clouddn.com/f6b64dc4bf7bee56.jpg', 'http://ac-c6scxa78.clouddn.com/91ead58b0bb213b6.jpg', 'http://ac-c6scxa78.clouddn.com/d67316858f6c71f3.jpg', 'http://ac-c6scxa78.clouddn.com/c81c5b7be1838a1e.jpg', 'http://ac-c6scxa78.clouddn.com/54fe022399902788.jpg', ]; //end 轮播图片加 class HomeScreen extends Component { //轮播图片加 constructor(props) { super(props); // 用于构建DataSource对象 var dataSource = new ViewPager.DataSource({ pageHasChanged: (p1, p2) => p1 !== p2, }); // 实际的DataSources存放在state中 //从网络获取标签 this._loadcatsandproject(); //end 从网络获取标签 this.state = { dataSource: dataSource.cloneWithPages(BANNER_IMGS), catid: "全部", //修改网络 categorys: [], } } //从网络获取标签 //https://segmentfault.com/q/1010000005813525 _loadcatsandproject() { return fetch('https://XXXXXXXX/wechat/cat', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ }) }) .then((response) => response.json()) .then((responseJson) => { this.setState({ categorys: responseJson.category, }) return responseJson.category; }) .catch((error) => { console.error(error); }) ; } _rendercatList(list) { console.log("进入模板map"); return list.map(item => this._itemcat(item)); } _itemcat(item) { console.log("输出每个标签模板"); return ( <View key={item.id} style={item.id==this.state.catid?styles.active:"" } ><Text key={item.id} style={styles.typebox} onPress={() => this._loadProduct(item.id)}> {item.name}</Text></View> ); } //end 从网络获取标签 //ViewPager播放的内部图片 _renderPage(data, pageID) { return ( <Image source={{ uri: data }} style={styles.page} /> ); } //end 轮播图片加 _loadProduct(catid) { var that = this; console.log(catid); this.setState({ catid: catid, }) } static navigationOptions = { title: '首页', }; /** dataSource: 提供页面数据, renderPage: 用于渲染页面视图, autoPlay: 为true 将自动播放, isLoop: 为true支持循环播放, locked: 为true禁止触摸滚动, onChangePage: 页面变化的回调, renderPageIndicator: 渲染自定义的 ViewPager indicator. */ render() { const { navigate } = this.props.navigation; //this._loadcatsandproject(); 千万不要放到模板中去,因为数据变化-模板会渲染-重新调用此句-会造成无线循环 return ( <View style={styles.container} > <View style={styles.swiper}> <ViewPager style={this.props.style} //样式 dataSource={this.state.dataSource} renderPage={this._renderPage} isLoop={true} autoPlay={true} /> </View> <View style={styles.scrollviewclass}> <ScrollView showsHorizontalScrollIndicator={false} horizontal={true} > <View style={"全部"==this.state.catid?styles.active:""}><Text style={styles.typebox} onPress={() => this._loadProduct('全部')}> 全部</Text></View> {this._rendercatList(this.state.categorys)} </ScrollView> </View> <Text onPress={() => navigate('item')} >{this.state.catid ? this.state.catid : "全部"}</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'flex-start', flexDirection: 'column', backgroundColor: '#F6F6F6', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, //分类部分 scrollviewclass: { height: 50, width: deviceWidth, backgroundColor: 'white' }, active: { borderBottomWidth: 1, borderBottomColor: 'red', }, typebox: { width: 70, fontSize: 18, lineHeight: 35, textAlign: 'center', }, //分类部分 //轮播图片加 swiper: { flexDirection: 'row', height: 200, }, page: { width: deviceWidth, height: 200, }, //end 轮播图片加 }); const HomeApp = StackNavigator({ home: { screen: HomeScreen }, item: { screen: ItemScreen }, }); export default HomeApp; |