React Native從零開始(八)ListView網絡獲取數據(Fetch)顯示

React Native從零開始(八)ListView網絡獲取數據(Fetch)顯示





先上效果圖:




一、思路


實現這個效果,我們需要了解ListView的實現和Fetch的實現方法,並將其結合,這兩個知識點在前兩篇博客中已經有寫到,其實沒有什麼難點,也可以加上頁面等待時的一個效果,在數據未加載完成時我們可以顯示Text,提示正在下載

二、實現

1、我們需要設置State來存儲數據的狀態,在未下載完成時爲false完成時則設置成true


    constructor(props){
        super(props);
        var ds = new ListView.DataSource({
           rowHasChanged:(oldRow,newRow) => oldRow!==newRow
        });
        this.state = {
            /*1設置初始值*/
            loaded: false,
            dataSource:ds
        };
    }

這個時候創建一個DataSource來判斷這兩行是否相同,就是是否發生變化,決定渲染哪些行組件,避免全部渲染,提高渲染效率。

2、創建一個方法來實現數據的下載

  //下載數據
    getData() {
    fetch(REQUEST_URL)
        .then((response) => {
            return response.json();
        })
        .then((responseData) => {
            this.setState({
                loaded:true,
                dataSource:this.state.dataSource.cloneWithRows(responseData.movies)
            });
        })
}

這裏第二個then的話是數據下載成功,我們將state的值重新賦值,然後將下載的數據克隆,是的dataSource不使用原數據。


3、使用componentDidMount方法來執行數據的下載,這個方法是在組件掛載後開始執行的

    //組件掛載完成後執行的方法
    componentDidMount(){
        //組件掛載後開始下載數據
        this.getData();
    }


4、渲染ListView的頭部、行、和分割線

//渲染行組件
function _renderRow(movie){
    return(
        <View style={styles.row}>
            <Image
                style={styles.thumbnail}
                source={{uri:movie.posters.thumbnail}}/>
            <View >
                <Text >{movie.title}</Text>
                <Text >{movie.year}</Text>
            </View>
        </View>
    );
}
//渲染頭部
function _renderHeader(){
    return(
        <View >
            <Text >Movies List</Text>
            <View ></View>
        </View>
    );
}
//渲染分割線
function _renderSeparator(sectionId,rowId){
    return(
        <View
            style={styles.separator}
            key={sectionId+rowId}></View>
    );
}



5、根據state的不同的值來渲染不同的控件


    render(){
        /*2如果未請求到數據提示等待加載,如果請求到數據顯示
         * */
        //加載前
        if(!this.state.loaded){
            return LoadingView();
        }
        //加載後
        return (
            <ListView
                style={styles.listView}
                dataSource={this.state.dataSource}
                renderRow={_renderRow}
                renderHeader={_renderHeader}
                renderSeparator={_renderSeparator}
                initialListSize={10}
            />
        );
    }

6、在index頁面調用這個控件就好

var MyListView = require("./MyView/MyListView");
export default class MovieListView extends Component {
  render() {
    return (
      <MyListView/>
    );
  }
}




三、最後附上所有代碼

MyListView.js

/**
 * Created by 11158 on 2017-01-17.
 */
import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Image,
    ListView
} from 'react-native';

var REQUEST_URL = "https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json";
/*
    邏輯:未獲取數據時,顯示等待頁面;獲得數據時,顯示電影列表頁面
    需要用到state的屬性,用於記錄下載狀態
* */
//未下載完數據顯示的頁面
function LoadingView() {
    return (
        <View style={styles.loadingContainer}>
            <Text style={styles.loadingText}>Loading Movies......</Text>
        </View>
    );
}
//渲染行組件
function _renderRow(movie){
    return(
        <View style={styles.row}>
            <Image
                style={styles.thumbnail}
                source={{uri:movie.posters.thumbnail}}/>
            <View >
                <Text >{movie.title}</Text>
                <Text >{movie.year}</Text>
            </View>
        </View>
    );
}
//渲染頭部
function _renderHeader(){
    return(
        <View >
            <Text >Movies List</Text>
            <View ></View>
        </View>
    );
}
//渲染分割線
function _renderSeparator(sectionId,rowId){
    return(
        <View
            style={styles.separator}
            key={sectionId+rowId}></View>
    );
}
class MyListView extends Component{
    constructor(props){
        super(props);
        var ds = new ListView.DataSource({
           rowHasChanged:(oldRow,newRow) => oldRow!==newRow
        });
        this.state = {
            /*1設置初始值*/
            loaded: false,
            dataSource:ds
        };
    }
    //組件掛載完成後執行的方法
    componentDidMount(){
        //組件掛載後開始下載數據
        this.getData();
    }
    //下載數據
    getData() {
    fetch(REQUEST_URL)
        .then((response) => {
            return response.json();
        })
        .then((responseData) => {
            this.setState({
                loaded:true,
                dataSource:this.state.dataSource.cloneWithRows(responseData.movies)
            });
        })
}
    render(){
        /*2如果未請求到數據提示等待加載,如果請求到數據顯示
         * */
        //加載前
        if(!this.state.loaded){
            return LoadingView();
        }
        //加載後
        return (
            <ListView
                style={styles.listView}
                dataSource={this.state.dataSource}
                renderRow={_renderRow}
                renderHeader={_renderHeader}
                renderSeparator={_renderSeparator}
                initialListSize={10}
            />
        );
    }
}

const styles = StyleSheet.create({
    //loading樣式
    loadingContainer:{
        flex:1,
        marginTop:25,
        backgroundColor:"cyan",
        justifyContent:"center",
        alignItems:"center"
    },
    loadingText:{
        fontSize:30,
        fontWeight:"bold",
        textAlign:"center",
        marginLeft:10
        ,marginRight:10
    },
    //行樣式
    row:{
        flexDirection:"row",
        padding:5,
        alignItems:"center",
        backgroundColor:"#F5FCFF"
    },
    //圖片樣式
    thumbnail:{
        width:53,
        height:81,
        backgroundColor:"gray"
    },
    //分割線樣式
    separator:{
        height:1,
        backgroundColor:"black"
    },
    listView:{
        marginTop:25,
        backgroundColor:"#F5FCFF"
    },
});

module.exports = MyListView;



index.android.js
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';
var MyListView = require("./MyView/MyListView");
export default class MovieListView extends Component {
  render() {
    return (
      <MyListView/>
    );
  }
}

const styles = StyleSheet.create({

});

AppRegistry.registerComponent('MovieListView', () => MovieListView);






大家可以加好友交流學習
QQ:1115856293
微信:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章