Fetch,WebSocket,XMLHttpRequest
(1) fetch網(wǎng)絡(luò)請(qǐng)求
getMoviesFromApiAsync() { //getMoviesFromApiAsync函數(shù)中使用fetch
return fetch('url地址',{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
.then((response) => response.json())
.then((dataJson) => {
return dataJson.key值;
})
.catch((error) => {
console.error(error);
});
}
- 實(shí)例 -
componentDidMount() { //在加載完成時(shí)執(zhí)行請(qǐng)求函數(shù)
this._fetchData();
}
_fetchData() {
fetch('http://image.baidu.com/channel/listjson?pn=0&rn=30&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&ie=utf8')
.then( (response) => response.json() )
.then( (dataJson) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(dataJson.data)
});
})
}
(2) mock.js來(lái)轉(zhuǎn)換請(qǐng)求過(guò)來(lái)的json格式
(1)npm install mockjs --save
(2)在node_modules - mockjs - dist - mock.js然后找到dataImage刪掉
(3)import Mock from 'mockjs'; (或者var Mock = require('mokjs');)
(4)Mock.mock('datajson');
(3) query-string參數(shù)字符串
- npm install query-string --save安裝
(4) lodash
- Lodash 就是這樣的一套工具庫(kù),它內(nèi)部封裝了諸多對(duì)字符串、數(shù)組、對(duì)象等常見(jiàn)數(shù)據(jù)類(lèi)型的處理函數(shù),其中部分是目前 ECMAScript 尚未制定的規(guī)范,但同時(shí)被業(yè)界所認(rèn)可的輔助函數(shù)。目前每天使用 npm 安裝 Lodash 的數(shù)量在百萬(wàn)級(jí)以上,這在一定程度上證明了其代碼的健壯性,值得我們?cè)陧?xiàng)目中一試。
上拉加載:
(1)ListView- onEndReached :預(yù)加載
(2)ListView- onEndReachedThreshold: 距地底部多大時(shí)預(yù)加載
(3)ListView- renderFooter:在列表的底部增加一欄,后面跟要執(zhí)行的函數(shù)(一般情況下用來(lái)顯示加載的loading動(dòng)畫(huà),俗稱(chēng)小菊花),這里有個(gè)大坑: 需要在后面加上.bind(this)
<listView
dataSource= { this.state.dataSource }
renderRow= { this._renderRow.bind(this) }
renderFooter = { this._renderFooter.bind(this) } //_renderFooter()函數(shù)在下面第4點(diǎn)中有
onEndReached = { this._onEndReached.bind(this) }
onEndReachedThreshold = { 20 }
/>
(4)ActivityIndicator :顯示一個(gè)圓形的loading提示符號(hào)。
- ActivityIndicator (indicator指示器的意思)
- 使用ActivityIndivator是要引用。import { ActivityIndicator } from 'react-native';
_renderFooter() {
if(!this.hasMore()){ //如果沒(méi)有更多數(shù)據(jù),展示文案
return (
<View>
<Text>沒(méi)有更多數(shù)據(jù)</Text>
</View>
)
}
else return <ActivityIndicator
style={[styles.centering, {height: 80}]}
size="large"
color="#ee735c"
/>
}
(5) showsVerticalScrollIndicator:隱藏ListView的縱向滾動(dòng)條;
showsVerticalScrollIndicator= { false }
- onEndReachedThreshold = { 20 } :距離底部20時(shí)預(yù)加載
- slice :slice() 方法可從已有的數(shù)組中返回選定的元素。4
arrayObject.slice(start,end)
start必須,規(guī)定從何處開(kāi)始選取;
end可選,規(guī)定從何處結(jié)束選取;
concat:concat() 方法用于連接兩個(gè)或多個(gè)數(shù)組。該方法不會(huì)改變現(xiàn)有的數(shù)組,而僅僅會(huì)返回被連接數(shù)組的一個(gè)副本。
setTimeout(function() { },2000)定時(shí)器,延時(shí)2s后執(zhí)行函數(shù)內(nèi)的內(nèi)容
下拉刷新:
(1) RefreshControl :下拉刷新組件
- 這一組件可以用在ScrollView或ListView內(nèi)部,為其添加下拉刷新的功能。當(dāng)ScrollView處于豎直方向的起點(diǎn)位置(scrollY: 0),此時(shí)下拉會(huì)觸發(fā)一個(gè)onRefresh事件。
- 使用時(shí),需要先引入該組件。 (記得要import引用哦)
- 屬性:
(1)onRefresh:在視圖開(kāi)始刷新時(shí)調(diào)用。(刷新時(shí)候,執(zhí)行的函數(shù))
(2)refreshing :視圖是否應(yīng)該在刷新時(shí)顯示指示器。(布爾值)
(3)colors:指定至少一種顏色用來(lái)繪制刷新指示器。
(4)progressBackgroundColor:指定刷新指示器的背景色。
(5)androidprogressViewOffset:指定刷新指示器的垂直起始位置(top offset)。
(6)size :指定刷新指示器的大小
<listView
dataSource= { this.state.dataSource }
renderRow= { this._renderRow.bind(this) }
renderFooter = { this._renderFooter.bind(this) } //_renderFooter()函數(shù)在下面第4點(diǎn)中有
onEndReached = { this._onEndReached.bind(this) }
onEndReachedThreshold = { 20 }
refreshControl= {
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={this._onRefresh}
tintColor="#ff0000"
title="Loading..."
titleColor="#00ff00"
colors={['#ff0000', '#00ff00', '#0000ff']}
progressBackgroundColor="#ffff00"
/>
}
/>
效果圖:
20170713132259.gif
2.png
完整代碼:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
Text,
Image,
ListView,
TouchableOpacity,
Dimensions,
ActivityIndicator,
RefreshControl
}from 'react-native';
// var MOCK = require('mockjs');
// import Request from '../common/request';
// var cachedResults = {
// nextPage =
// }
var width = Dimensions.get('window').width;
// var height = Dimensions.get('window').height;
// var cachedResults = {
// nextPage: 1, //下一頁(yè)
// items: [ ], // 緩存的數(shù)據(jù)列表
// total: 0 //所有的列表的總長(zhǎng)度
//
// };
let ip = [];
let page = 1;
export default class List extends Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([ {
"id": "710000201512201032",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
},
{
"id": "540000201705130953",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
},
{
"id": "36000020090726779X",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
},
{
"id": "23000019890819858X",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
},
{
"id": "810000199101084138",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
},
{
"id": "810000198412233773",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
},
{
"id": "610000200610314331",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
},
{
"id": "360000201607162472",
"image_url": "http://g1.ykimg.com/050C0000595C3945ADC0AEC7BF085F58",
"video": "http://www.imooc.com/static/lib/mocoplayer/2.5.1/mocoplayer.swf?v=2.4.3"
}
]),
isLoadingTail: false,
isRefreshing: false
};
}
//ListView的renderRow方法
_renderRow(rowData, sectionID, rowID) {
return (
<TouchableOpacity>
<View>
<View style={ styles.titleContainer}>
<Text style={styles.title}>美女和男神的養(yǎng)成密集,讓趙麗穎來(lái)告訴你</Text>
</View>
<View>
<Image source={{ uri: rowData.image_url }} style={styles.img}></Image>
<Image source={ require('../../go.png') } style={styles.go}></Image>
</View>
<View style={styles.bottom}>
<View style={styles.bottomBoth}>
<Image style={styles.sLogo} source={ require('../../love.png') }></Image>
<Text style={ styles.bottomText}>喜歡</Text>
</View>
<View style={styles.bottomBoth}>
<Image style={styles.sLogo2} source={ require('../../discuss.png') }></Image>
<Text style={ styles.bottomText}>評(píng)論</Text>
</View>
</View>
</View>
</TouchableOpacity>
);
}
// componentDidMount() {
// this._fetchData(1);
// }
// _fetchData() {
//
// }
// // 調(diào)用fetchData
// componentDidMount() {
// this._fetchData();
// }
// fetch網(wǎng)絡(luò)請(qǐng)求
// _fetchData() {
// return(
// request.get(config.api.base + config.api.creations , { accessToken: '111112223' })
// .then((response) => response.json())
// .then((response) => {
// // var data = MOCK.mock(response);
// // console.log(data);
//
// console.log(response);
// })
// .catch((error) => {
// console.error(error);
// })
// );
// }
// _hasMore() {
// return cachedResults.items.length !== cachedResults.total;
// }
componentDidMount() {
this.getData(1,3)
}
getData(page,rn) {
this.setState({
isLoadingTail: true
});
let newUrl = 'http://image.baidu.com/channel/listjson?pn='+ page + '&rn='+ rn +'&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&ie=utf8';
fetch(newUrl)
.then( (response) => response.json())
.then( (dataJson) => {
ip = dataJson.data;
this.setState({
isLoadingTail: false,
dataSource: this.state.dataSource.cloneWithRows(dataJson.data)
});
})
.catch( (error) => {
console.error(error);
})
}
hasMore() {
return ip != 100;
}
onEndReached() {
if( !this.hasMore() || this.state.isLoadingTail){
return
}
var that = this;
page = page+20;
var rn =5;
fetch('http://image.baidu.com/channel/listjson?pn='+ page + '&rn='+ rn +'&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&ie=utf8')
.then( (response) => response.json())
.then( (dataJson) => {
ip = ip.slice().concat(dataJson.data);
setTimeout(function(){
that.setState({
dataSource: that.state.dataSource.cloneWithRows(ip)
})
},2000);
})
.catch( (error) => {
console.error(error);
})
}
_renderFooter() {
if(!this.hasMore()){
return (
<View>
<Text>沒(méi)有更多數(shù)據(jù)</Text>
</View>
)
}
else return <ActivityIndicator
style={[styles.centering, {height: 80}]}
size="large"
color="#ee735c"
/>
}
_onRefresh() {
if(!this.hasMore() || this.state.isRefreshing){
return
}
this.setState({
isRefreshing: false
});
page= page+20;
var rn = 4;
fetch('http://image.baidu.com/channel/listjson?pn='+ page + '&rn='+ rn +'&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&ie=utf8')
.then( (response) => response.json())
.then( (dataJson) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(dataJson.data)
})
})
}
render() {
return (
<View style={styles.content}>
<View style={ styles.header}>
<Text style={styles.headerTitle}>
列表頁(yè)
</Text>
</View>
<ListView
dataSource={this.state.dataSource}
renderRow={ this._renderRow.bind(this) }
renderFooter={ this._renderFooter.bind(this)}
onEndReached={ this.onEndReached.bind(this)}
onEndReachedThreshold = { 100 }
enableEmptySections = { true }
automaticallyAdjustContentInserts = { false }
showsVerticalScrollIndicator = { false }
refreshControl= {
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={this._onRefresh.bind(this)}
tintColor="#ff0000"
title="Loading..."
titleColor="#00ff00"
colors={['#ff0000', '#00ff00', '#0000ff']}
progressBackgroundColor="#fff"
/>
}
/>
</View>
)
}
}
const styles = StyleSheet.create({
content: {
flex:1,
// justifyContent: 'center',
// alignItems: 'center'
},
header: {
backgroundColor: '#ee735c',
paddingTop:16,
paddingBottom:16
},
headerTitle: {
color:'white',
fontWeight: '600',
textAlign: 'center',
fontSize: 18,
letterSpacing: 300,
},
img: {
width: width,
height: 300
},
go: {
position: 'absolute',
width: 50,
height: 50,
bottom: 30,
right:60
},
title: {
fontSize: 20,
letterSpacing: 18
},
titleContainer: {
height:46,
marginTop:14
},
bottom: {
height:60,
paddingBottom:84,
flexDirection: 'row',
justifyContent: 'space-between',
backgroundColor:"#eee"
},
bottomBoth: {
flexDirection: 'row',
justifyContent: 'center',
width: width / 2 - 0.5,
backgroundColor:"white",
height:70,
paddingTop: 4,
alignItems: 'center'
},
sLogo: {
width: 38,
height:38,
marginRight: 8
},
sLogo2: {
width: 42,
height:44,
marginRight: 8
},
bottomText: {
fontSize: 20
},
centering: {
flexDirection: 'row',
justifyContent: 'center'
}
});