閱讀359 返回首頁    go 阿裏雲 go 技術社區[雲棲]


React Native項目實戰之fetch請求

fetch簡介

在 AJAX 時代,進行請求 API 等網絡請求都是通過XMLHttpRequest 或者封裝後的框架進行網絡請求。而在前端快速發展地過程中,為了契合更好的設計模式,產生了 fetch 框架。 fetch相比XMLHttpRequest,提供更加強大、高效的網絡請求方式,所以在 Hybrid App 開發模式中,大量的用到了fetch框架作為網絡請求。

fetch在瀏覽器中使用

在 Chrome 瀏覽器中已經全局支持了 fetch 函數,打開調試工具,在 Console 中可以進行體驗下fetch。先不考慮跨域請求的使用方法,我們先請求同域的資源。例如:

fetch("https://blog.csdn.net/xiangzhihong8").then(function(response){console.log(response)}) 

fetch語法

使用 fetch 的構造函數請求數據後,返回一個 Promise 對象,然後根據具體的實際情況處理。

fetch("https://baidu.com")  
.then(function(response){  
   // ...
})

說明,在請求後的 Response 中,常常有如下返回情況:

  • Response.status 也就是 StatusCode,如成功就是 200 ;
  • Response.statusText 是 StatusCode 的描述文本,如成功就是 OK ;
  • Response.ok 一個 Boolean 類型的值,判斷是否正常返回,也就是 StatusCode 為 200-299 。

fetch請求實例

1.使用get方式進行網絡請求,例如:

fetch('https://nero-zou.com/test', {  
    method: 'GET'
}).then(function(response) {
    //獲取數據,數據處理
}).catch(function(err) {
    //錯誤處理
});

2.使用post方式進行網絡請求,例如:

let param = {user:'xxx',phone:'xxxxxx'};
fetch(url, {  
    method: 'post',
    body: JSON.stringify(param)
}).then(function(response) {
    //獲取數據,數據處理
});

3.其它寫法,例如:

try {
       fetch(url, {  
            method: 'post',
            body: JSON.stringify(param)
        }).then(function(response) {
            //獲取數據,數據處理
        });  
    } catch(e) {
         //捕獲異常消息    
    }

4.帶header 或其它參數,例如:

fetch(url, {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  })
})

fetch請求並填充界麵

我們先看看使用fetch並填充界麵後的完整效果。
這裏寫圖片描述
這裏寫圖片描述

要實現上麵的效果,我們需要對數據進行監聽,也就是所謂的狀態機機製。

state: {
        discounts: Array<Object>,
        dataSource: ListView.DataSource
    }

然後我們使用fetch進行網絡請求,當有數據返回時,我們更改數據源的數據。

 requestDiscount() {
        fetch(api.discount)
            .then((response) => response.json())
            .then((json) => {
                console.log(JSON.stringify(json));
                this.setState({ discounts: json.data })
            })
            .catch((error) => {
                alert(error)
            })
    }

那麼什麼時候出發這個請求呢?當我們界麵掛載的時候就觸發這個請求,所以我們在componentDidMount調用這個請求。

componentDidMount() {
       this.requestDiscount();
    }

請求的接口如下:
https://api.meituan.com/group/v1/deal/topic/discount/city/1?ci=1&client=iphone&movieBundleVersion=100&msid=48E2B810-805D-4821-9CDD-D5C9E01BC98A2015-06-17-14-50363&userid=10086&utm_campaign=AgroupBgroupD100Fab_chunceshishuju__a__a___b1junglehomepagecatesort__b__leftflow___ab_gxhceshi__nostrategy__leftflow___ab_gxhceshi0202__b__a___ab_pindaochangsha__a__leftflow___ab_xinkeceshi__b__leftflow___ab_gxtest__gd__leftflow___ab_gxh_82__nostrategy__leftflow___ab_pindaoshenyang__a__leftflow___i_group_5_2_deallist_poitype__d__d___ab_b_food_57_purepoilist_extinfo__a__a___ab_trip_yidizhoubianyou__b__leftflow___ab_i_group_5_3_poidetaildeallist__a__b___ab_waimaizhanshi__b__b1___a20141120nanning__m1__leftflow___ab_pindaoquxincelue__a__leftflow___ab_i_group_5_5_onsite__b__b___ab_i_group_5_6_searchkuang__a__leftflow&utm_content=4B8C0B46F5B0527D55EA292904FD7E12E48FB7BEA8DF50BFE7828AF7F20BB08D&utm_medium=iphone&utm_source=AppStore&utm_term=5.7&uuid=4B8C0B46F5B0527D55EA292904FD7E12E48FB7BEA8DF50BFE7828AF7F20BB08D&version_name=5.7

返回的內容如下:

{
stid: "836121754643660800",
data: [
{
typeface_color: "#ff9900",
position: 0,
module: false,
maintitle: "今日爆款",
type: 1,
deputytitle: "5折來按摩",
solds: 0,
id: 19995,
share: {
message: "養生名店1折起,最高立減30元,",
url: "https://g.meituan.com/app/gfe-app-page-discount/index-mt.html"
},
title: "今日爆款",
deputy_typeface_color: "#21c0ae",
tplurl: "imeituan://www.meituan.com/web?url=https://g.meituan.com/app/gfe-app-page-discount/index-mt.html",
imageurl: "https://p0.meituan.net/w.h/feop/0044b4cebe650ada958da3458f51eae833656.png"
},
{
typeface_color: "#f6687d",
position: 0,
module: false,
maintitle: "電影特惠",
type: 1,
deputytitle: "神奇女俠",
solds: 0,
id: 19749,
share: {
message: "熱門大片特惠,福利再來一波>>",
url: "https://i.meituan.com/firework/km1495594906"
},
title: "電影特惠",
deputy_typeface_color: "#c280fc",
tplurl: "imeituan://www.meituan.com/web?url=https://i.meituan.com/firework/km1495594906",
imageurl: "https://p1.meituan.net/w.h/feop/6d7deddaeecd3b6c1181902616f2b4c028136.png"
},
{
typeface_color: "#6bbd00",
position: 0,
module: false,
maintitle: "特價出遊",
type: 1,
deputytitle: "泰國跟團清倉",
solds: 0,
id: 20001,
share: {
message: "特價出遊,泰國跟團清倉",
url: "http%3a%2f%2fi.meituan.com%2ffirework%2fislandseasonMT"
},
title: "特價出遊",
deputy_typeface_color: "#fc6a56",
tplurl: "imeituan://www.meituan.com/web?url=http%3a%2f%2fi.meituan.com%2ffirework%2fislandseasonMT",
imageurl: "https://p1.meituan.net/w.h/feop/80fe92619a56f760e06e8c84657acb9720105.png"
},
{
typeface_color: "#06c1ae",
position: 0,
module: false,
maintitle: "今日推薦",
type: 1,
deputytitle: "品質生活指南",
solds: 0,
id: 3283,
share: {
message: "吃喝玩樂全都有,盡在美團網!",
url: "https://api.mobile.meituan.com/group/v1/re/p"
},
title: "今日推薦",
deputy_typeface_color: "#fdb32b",
tplurl: "imeituan://www.meituan.com/recommend?url=https://api.mobile.meituan.com/group/v1/re/p",
imageurl: "https://p0.meituan.net/w.h/feop/24ab8d4d0c2bd36bb4b95d2a8c0b105236553.png"
}
],
server: {
time: 1496411274
},
paging: {
count: 4
}
}

到此,數據請求基本完成了,接下來就是怎麼將數據繪製到界麵上的問題。為了方便我們需要自定義一個GridView用來繪製這個九宮格界麵。我們在render()中定義一個props來接受請求返回的數據。代碼如下:

class GridView extends Component {

    static defaultProps = {
        infos: []
    }

    render() {
        let { infos } = this.props
        let gridItems = []
        for (let i = 0; i < infos.length; i++) {
            let gridItem = (
                <GridItem info={infos[i]} key={i} onPress={() => this.props.onGridSelected(i)}/>
            )
            gridItems.push(gridItem)
        }

        return (
            <View style={styles.container}>
                {gridItems}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        justifyContent: 'space-between',
        borderTopWidth: 1,
        borderLeftWidth: 1,
        borderColor: '#e9e9e9'
    },
});

export default GridView;

然後我們在繪製每一個GridItem,這個有點類似於Android的Adapter或者ios的CollectionViewCell。代碼如下,不做詳細的介紹:

var Dimensions = require('Dimensions');
var screen = Dimensions.get('window');

class GridItem extends Component {
    render() {
        let info = this.props.info

        let title = info.maintitle
        let color = info.typeface_color
        let subtitle = info.deputytitle
        let imageUrl = info.imageurl.replace('w.h', '120.0').replace('http','https')



        return (
            <TouchableOpacity style={styles.container} onPress={this.props.onPress}>
                <View>
                    <Heading1 style={{ color: color, marginBottom: 10}}>{title}</Heading1>
                    <Heading2 >{subtitle}</Heading2>
                </View>

                <Image style={styles.icon} source={{ uri: imageUrl}} />
            </TouchableOpacity>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        width: screen.width / 2 - 1,
        height: screen.width / 4,
        backgroundColor: 'white',
        borderBottomWidth: 1,
        borderRightWidth: 1,
        borderColor: '#e9e9e9'
    },
    icon: {
        width: screen.width / 5,
        height: screen.width / 5,
    }
});

export default GridItem;

到此我們就完成了fetch請求並繪製界麵的功能。
附:本文源碼
fetch請求二次封裝

最後更新:2017-06-02 23:01:41

  上一篇:go  實習生麵試隨手記
  下一篇:go  阿裏雲備案的最新方式和阿裏雲APP備案核驗佳速互聯操作流程