《React Native 精解與實戰》書籍連載「React Native 網絡請求與列表綁定」

截圖

此文是個人出版書籍《React Native 精解與實戰》連載分享,此書由機械工業出版社出版,書中詳解了 React Native 框架底層原理、React Native 組件佈局、組件與 API 的介紹與代碼實戰,以及 React Native 與 iOS、Android 平臺的混合開發底層原理講解與代碼實戰演示,精選了大量實例代碼,方便讀者快速學習。node

書籍還配套了視頻教程「80 節實戰課精通 React Native 開發」,此視頻課程建議配合書籍學習,書籍中原理性的東西講解的比較清晰,而視頻教程對於組件、API 等部分的代碼實戰開發講解比較直觀。react

書籍相關全部資料請訪問:http://rn.parryqiu.comjson

<!--more-->segmentfault

相關連載更新
《React Native 精解與實戰》書籍連載「React 與 React Native 簡介」
《React Native 精解與實戰》書籍連載「React Native 底層原理」
《React Native 精解與實戰》書籍連載「Node.js 簡介與 React Native 開發環境配置」
《React Native 精解與實戰》書籍連載「React Native 中的生命週期」
原創「80節實戰課精通 React Native 開發」視頻課程大綱react-native

8.4 React Native 網絡請求與列表綁定方案

下面咱們就經過結合 Fetch API 以及 React Native 框架中的列表組件,經過代碼實戰的形式進行這兩個重要知識點的學習。
首先咱們數據獲取使用豆瓣的公開 API,獲取目前正在上映的 20 部電影的信息,豆瓣 API 地址爲:https://api.douban.com/v2/mov...,API 接口返回的 JSON 數據如圖 8-6 所示。api

截圖
圖 8-6 豆瓣 API 返回的 JSON 數據安全

在此示例代碼中,將採用組件開發的思想,首頁加載 4 個 Tab,每個 Tab 加載對應的頁面組件。這裏的列表加載在第一個 Tab 中,組件定義爲 Home,在項目中創建的文件名爲 home.js。
完整代碼在本書配套源碼的 08-03 文件夾。網絡

1.    /** 
2.     * 章節: 08-03 
3.     * App.js 定義了項目的大結構,使用 4 個 Tab 進行佈局。 
4.     * FilePath: /08-03/ListDemo/App.js 
5.     * @Parry 
6.     */  
7.      
8.    import React, {Component} from 'react';  
9.    import {Platform, StyleSheet, Text, View, Image} from 'react-native';  
10.    import TabNavigator from 'react-native-tab-navigator';  
11.    import HomePage from './home';  
12.      
13.    export default class App extends Component < {} > {  
14.      
15.      state = {  
16.        selectedTab: 'home'  
17.      };  
18.      
19.      _renderContent = (color : string, index : string) => {  
20.        switch (index) {  
21.          case "home":  
22.            return (<HomePage/>);  
23.        }  
24.      };  
25.      
26.      render() {  
27.        return (  
28.          <TabNavigator>  
29.            <TabNavigator.Item  
30.              selected={this.state.selectedTab === 'home'}  
31.              title="首頁"  
32.              renderIcon={() => <Image  
33.              style={ {  
34.              width: 25,  
35.              height: 25  
36.            } }  
37.              source={require('./flux.png')}/>}  
38.              renderSelectedIcon={() => <Image  
39.              style={ {  
40.              width: 25,  
41.              height: 25  
42.            } }  
43.              source={require('./relay.png')}/>}  
44.              onPress={() => this.setState({selectedTab: 'home'})}>  
45.              {this._renderContent('#FFFFFF', 'home')}  
46.            </TabNavigator.Item>  
47.      
48.            ...... //此處省略了其餘三個 Tab 的定義  
49.                   //完整代碼在書籍的配套源碼中  
50.              
51.          </TabNavigator>  
52.        );  
53.      }  
54.    }

上面這段代碼爲 App.js 的部分主要邏輯,注意在代碼的第 11 行導入外部 Home 組件的方法,以及針對以前 Tab 組件章節的邏輯修改了加載對應組件的方法,主要爲代碼第 20 行的部分。框架

1.    /** 
2.     * 章節: 08-03 
3.     * home.js 定義了第一個 Tab 加載的頁面組件,用於加載豆瓣電影列表 
4.     *         同時演示了 ListView 綁定方法 
5.     * FilePath: /08-03/ListDemo/home.js 
6.     * @Parry 
7.     */  
8.      
9.    import React, {Component} from 'react';  
10.    import {  
11.        Platform,  
12.        StyleSheet,  
13.        Text,  
14.        View,  
15.        Image,  
16.        ListView,  
17.        SafeAreaView  
18.    } from 'react-native';  
19.      
20.    export default class HomePage extends Component < {} > {  
21.      
22.        constructor(props) {  
23.            super(props);  
24.            this.state = {  
25.                dataSource: new ListView.DataSource({ //定義數據源  
26.                    rowHasChanged: (row1, row2) => row1 !== row2  
27.                }),  
28.                loaded: false  
29.            };  
30.        }  
31.      
32.        componentDidMount() {  
33.            this.fetchData(); //開始請求數據  
34.        };  
35.      
36.        fetchData() {  
37.            fetch("https://api.douban.com/v2/movie/in_theaters").then((response) => response.json()).then((responseData) => {  
38.                this.setState({  
39.                    dataSource: this  
40.                        .state  
41.                        .dataSource  
42.                        .cloneWithRows(responseData.subjects), //讀取返回的全部電影數據  
43.                    loaded: true  
44.                });  
45.            }).done();  
46.        };  
47.      
48.        render() {  
49.            return (  
50.                <View style={styles.container}>  
51.                    <ListView automaticallyAdjustContentInsets={false} //此選項能夠修復掉會自動多出來的大約 10px 的空行  
52.                        dataSource={this.state.dataSource} renderRow={this._renderRow}/>  
53.                </View>  
54.            );  
55.        };  
56.      
57.        _renderRow(rowData, sectionID, rowID) {  
58.            return (  
59.                <SafeAreaView>  
60.                    <View style={styles.row}>  
61.                        <Image  
62.                            style={styles.thumb}  
63.                            source= { { 
64.                            uri: rowData.images.large  
65.                            } } />  
66.                        <View style={styles.texts}>  
67.                            <Text style={styles.textTitle}>  
68.                                {rowData.title}  
69.                            </Text>  
70.                            <Text style={styles.textTitle}>  
71.                                年份: {rowData.year}  
72.                            </Text>  
73.                            <Text style={styles.textTitle}>  
74.                                豆瓣評分: {rowData.rating.average}  
75.                            </Text>  
76.                        </View>  
77.                    </View>  
78.                    <View style={styles.separator}/>  
79.                </SafeAreaView>  
80.            );  
81.        };  
82.    }  
83.      
84.    var styles = StyleSheet.create({  
85.        container: {  
86.            flex: 1  
87.        },  
88.        row: {  
89.            flexDirection: 'row',  
90.            padding: 10  
91.        },  
92.        separator: {  
93.            height: 1,  
94.            backgroundColor: '#EEEEEE'  
95.        },  
96.        thumb: {  
97.            width: 60,  
98.            height: 80,  
99.            borderRadius: 2  
100.        },  
101.        textTitle: {  
102.            flex: 1,  
103.            textAlign: "left",  
104.            paddingLeft: 10,  
105.            fontWeight: "bold",  
106.            flexDirection: 'row',  
107.            color: "#666666"  
108.        },  
109.        texts:{  
110.            flexDirection: 'column',  
111.            paddingTop: 5  
112.        }  
113.    });

上面代碼爲 Home 組件的實現方法,下面主要對代碼中的一些重要邏輯做一些說明:佈局

  • 代碼在 17 行導入了一個新的 View 組件,SafeAreaView 用於在 iPhone X 下佈局 View 而控制整個 View 安全佈局於手機的可視區域中;
  • 代碼的第 25 - 27 行,定義了 ListView 的數據源,同時定義了 rowHasChanged 的邏輯;
  • 代碼第 32 行在生命週期 componentDidMount 中定義了從 API 中加載數據的方法;
  • 代碼第 36 - 46 行定義了從豆瓣 API 使用 Fetch API 請求數據的方法,注意對 Fetch API 返回的 Promise 對象的處理方法;
  • 代碼第 51 行定義了 ListView 綁定的方法,行渲染的方法爲代碼中第 57 行定義的方法 _renderRow;
  • 代碼第 57 - 81 行定義了列表渲染的方法,使用 View 與 Text 組件進行了列表的展現佈局;
  • 後續的樣式定義如以前學習的樣式定義同樣,進行精細布局控制便可。
    項目運行在 iOS 平臺的效果如圖 8-7 所示,Android 平臺你們也能夠直接下載本書配套源碼在本地學習、測試與運行。

截圖
圖 8-7 iOS 下的 ListView 運行效果

8.5 本章小結

列表綁定是 App 開發最經常使用的一個開發功能,你能夠隨手打開本身手機上的 App 就會發現許多 App 的首頁都是進行了數據請求、列表綁定或列表數據刷新等動做,這也真是移動互聯網的魅力所在,用戶能夠隨時獲取到最新的資訊信息。因此此章節是一個重要的章節,並從底層知識點到實戰代碼都進行了詳細地講解與演示,但願能幫助你開發出你的 App 的首頁列表組件。
我的技術視頻博客站點:https://devopen.club/

相關文章
相關標籤/搜索