• React Native 项目实战 -- DoubanProject


    引言:本文是我研究react-native时写的一个简单的demo,代码里有详细的注释,好废话不多说,直接上代码。

    1.项目目录

    2.index.android.js

    /**
     * index.android.js 入口文件
     * Sample React Native App
     * https://github.com/facebook/react-native
     * @flow
     */
    // icon={require("image!book")}
    // icon={require("image!movie")}
    
    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      Image,
      StatusBar
    } from 'react-native';
    
    // 导入导航器
    var Navigation = require("./android_views/common/navigation");
    // 导入BookList
    var BookList = require("./android_views/book/book_list");
    // 导入MovieList
    var MovieList = require("./android_views/movie/movie_list");
    
    // tab组件
    import TabNavigator from 'react-native-tab-navigator';
    
    // 隐藏状态栏
    StatusBar.setHidden(true);
    
    // TabNavigator管理两个模块:图书、电影
    var DoubanProject = React.createClass({
      getInitialState: function() {
        return {
          selectedTab: "图书"
        };
      },
      render: function() {
        return (
          <TabNavigator>
            <TabNavigator.Item
              // 标题
              title="图书"
              // 设置选中的位置
              selected={this.state.selectedTab=="图书"}
              // 点击Event
              onPress={() => {
                this.setState({
                  selectedTab:"图书"
                })
              }}
              //图标
              renderIcon={() => <Image style={styles.icon} source={require("./res/images/book.png")} />}
              //选中时图标
              renderSelectedIcon={() => <Image style={[styles.icon,{tintColor:'#2f8fe6'}]} source={require("./res/images/book.png")} />}>
              <Navigation component={BookList}/>
            </TabNavigator.Item>
              
            <TabNavigator.Item
              // 标题
              title="电影"
              // 设置选中的位置
              selected={this.state.selectedTab=="电影"}
              // 点击Event
              onPress={() => {
                this.setState({
                  selectedTab:"电影"
                })
              }}
              //图标
              renderIcon={() => <Image style={styles.icon} source={require("./res/images/movie.png")} />}
              //选中时图标
              renderSelectedIcon={() => <Image style={[styles.icon,{tintColor:'#2f8fe6'}]} source={require("./res/images/movie.png")} />}>
              <Navigation component={MovieList}/>
            </TabNavigator.Item>
          </TabNavigator>
        )
      }
    });
    
    const styles = StyleSheet.create({
        icon: {
             22,
            height: 22
        }
    });
    
    AppRegistry.registerComponent('DoubanProject', () => DoubanProject);
    

    3.service.js

    /*
    	1.接口 API
    	基于豆瓣开放API的图书、电影
    */
    
    var BaseURL = "https://api.douban.com/v2/";
    
    var Douban_APIS = {
    	/*
    	图书搜索
    
    	image  图书缩略图
    	title  图书名称
    	publisher  出版社
    	author  作者
    	price  价格
    	pages  图书总页数
    	*/
    	book_search: BaseURL + "book/search",
    
    	/*
    	图书详情
    
    	image  图书缩略图
    	title  图书名称
    	publisher  出版社
    	author  作者
    	price  价格
    	pages  图书总页数
    	summary  图书简介
    	author_intro  作者简介
    	*/
    	book_detail_id: BaseURL + "book/",
    
    	/*
    	电影搜索
    
    	images.medium  电影图像
    	title  电影名称
    	casts  电影演员  数据需要再处理
    	rating.average  电影评分
    	year  电影上映时间
    	genres  电影标签
    	alt  电影详情url
    	*/
    	movie_search: BaseURL + "movie/search",
    }
    
    // 导出
    module.exports = Douban_APIS;
    

    4.util.js

    /*
    	2.定义工具类
    
    	实现功能:定义多个属性,在项目中会使用的一些功能。包括:获取屏幕尺寸、loading组件、GET请求方法
    
    	包含组件:
    
    	外部引用:
    
    		GET请求方法需要从外部引入url、请求成功的回调方法、请求失败的回调方法。
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	Dimensions, // 用于获取设备屏幕的宽高
    	ActivityIndicator // loading组件
    } from 'react-native';
    
    // 定义对象,将提供的功能作为属性存放
    var Util = {
    	// 屏幕尺寸
    	windowSize: {
    		 Dimensions.get("window").width,
    		height: Dimensions.get("window").height
    	},
    
    	// 基于fetch的get方法  只负责下载数据,下载后的处理操作在回调方法中实现
    	// successCallback 数据下载成功的回调方法,在组件中实现
    	// failCallback 数据下载失败的回调方法,在组件中实现
    	getRequest: function(url, successCallback, failCallback) {
    		fetch(url)
    			.then((response) => response.json())
    			.then((responseData) => successCallback(responseData))
    			.catch((error) => failCallback(error));
    	},
    
    	// loading效果
    	loading: <ActivityIndicator style={{marginTop:200}} />
    }
    
    // 导出
    module.exports = Util;
    

    5.searchBar.js

    /*
    	3.实现功能:封装搜索栏组件,包括文本输入框和搜索按钮
    
    	包含组件:
    
    	外部传入:
    		输入框和按钮的属性设置由外部引入。例如:placeholder、onPress、onChangeText
    		使用...this.props将外部传入的属性设置给TextInput和TouchableOpacity
    
    		注意:指定高度、边框颜色、边框线框
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	TextInput,
    	TouchableOpacity
    } from 'react-native';
    
    // 定义组件
    var SearchBar = React.createClass({
    	render: function() {
    		return (
    			<View style={styles.container}>
    				<View style={styles.inputContainer}>
    					<TextInput style={styles.input} {...this.props} />
    				</View>
    
    				<TouchableOpacity style={styles.btn} {...this.props}>
    					<Text style={styles.search}>搜索</Text>
    				</TouchableOpacity>
    			</View>
    		);
    	}
    });
    
    var styles = StyleSheet.create({
    	container: {
    		flexDirection: "row",
    		justifyContent: "flex-end",
    		alignItems: "center",
    		height: 44,
    		marginTop: 10
    	},
    	inputContainer: {
    		flex: 1,
    		marginLeft: 5
    	},
    	input: {
    		flex: 1,
    		height: 44,
    		borderWidth: 1,
    		borderRadius: 4,
    		borderColor: "#CCC",
    		paddingLeft: 5
    	},
    	btn: {
    		 55,
    		height: 44,
    		marginLeft: 5,
    		marginRight: 5,
    		backgroundColor: "#23BEFF",
    		borderRadius: 4,
    		justifyContent: "center",
    		alignItems: "center"
    	},
    	search: {
    		flex: 1,
    		color: "#fff",
    		fontSize: 15,
    		fontWeight: "bold",
    		textAlign: "center",
    		lineHeight: 34
    	}
    });
    
    module.exports = SearchBar;
    

    6.left_icon.js

    /*
    	4.实现功能:封装返回按钮图标,不使用图片
    
    	包含组件:
    
    	外部传入:
    */
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View
    } from 'react-native';
    
    // 定义组件 返回图标
    var Icon = React.createClass({
    	render: function() {
    		return (
    			<View>
    				<View style={styles.go}></View>
    			</View>
    		);
    	}
    });
    
    var styles = StyleSheet.create({
    	go: {
    		 15,
    		height: 15,
    		borderLeftWidth: 2,
    		borderBottomWidth: 2,
    		borderColor: "#fff",
    		marginLeft: 10,
    		transform: [{rotate: "45deg"}] // 将一个矩形框旋转了45度
    	}
    });
    
    module.exports = Icon;
    

    7.header.js

    /*
    5.实现功能:封装header,在头部展示标题和返回按钮
    
    包含组件:
    
    外部传入:
    	navigator 点击返回按钮返回上一级页面
    	initObj(backName、barTitle)  返回按钮的名称、标题
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	TouchableOpacity
    } from 'react-native';
    
    // 导入左侧按钮
    var Icon = require("./left_icon");
    
    var Header = React.createClass({
    	render: function() {
    		// 获取obj对象,包括:backName(按钮名称)、barTitle
    		var headerContent = this.props.initObj;
    
    		return (
    			<View style={styles.header}>
    				<TouchableOpacity style={styles.left_btn} onPress={this._pop}>
    					<Icon />
    					<Text style={styles.btn_next}>{headerContent.backName}</Text>
    				</TouchableOpacity>
    
    				<View style={styles.title_container}>
    					<Text style={styles.title} numberOfLines={1}>{headerContent.barTitle}</Text>
    				</View>
    			</View>
    		);
    	},
    	// 返回按钮事件处理方法
    	_pop: function() {
    		this.props.navigator.pop();
    	}
    });
    
    var styles = StyleSheet.create({
    	header: {
    		height: 44,
    		backgroundColor: "#3497FF",
    		flexDirection: "row",
    		justifyContent: "center",
    		alignItems: "center"
    	},
    	left_btn: {
    		flexDirection: "row",
    		justifyContent: "center",
    		alignItems: "center"
    	},
    	btn_text: {
    		color: "#fff",
    		fontSize: 17,
    		fontWeight: "bold"
    	},
    	title_container: {
    		flex: 1,
    		justifyContent: "center",
    		alignItems: "center"
    	},
    	title: {
    		color: "#fff",
    		fontSize: 18,
    		fontWeight: "bold",
    		lineHeight: 18,
    		 200
    	}
    });
    
    module.exports = Header;
    

      

    8.navigation.js

    /*
    	6.实现功能:封装导航器初始化设置
    
    	包含组件:Navigator
    
    	外部传入:
    		component  需要展示的页面组件
    		route对象  必须添加component属性; 如果需要传值可以添加passProps属性
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View
    } from 'react-native';
    
    // npm install react-native-deprecated-custom-components --save
    
    import CustomerComponents, { Navigator } from 'react-native-deprecated-custom-components';
    
    var Navigation = React.createClass({
    	render: function() {
    		// 创建route对象,约定格式
    		var rootRoute = {
    			component: this.props.component,
    			passProps: {
    				
    			}
    		};
    
    		return (
    			<Navigator
    				initialRoute={rootRoute}
    				configureScene={() => {return Navigator.SceneConfigs.PushFromRight}}
    				renderScene={(route,navigator) => {
    					var Component = route.component;
    					return (
    						<View style={{flex:1}}>
    							<Component
    								navigator={navigator}
    								route={route}
    								{...route.passProps}/>
    						</View>
    					);
    				}}/>
    		);
    	}
    });
    
    module.exports = Navigation;
    

      

    9.customWebView.js

    /*
    	7.实现功能:封装WebView,根据传入的url展示网页信息
    
    	包含组件:Header、WebView
    
    	外部传入:
    		给Header设置:navigator、initObj(backName、title)
    		给WebView设置:source(url)
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	WebView
    } from 'react-native';
    
    var Header = require("./header");
    
    var CustomWebView = React.createClass({
    	render: function() {
    		return (
    			<View style={{backgroundColor:"white",flex:1}}>
    				<Header 
    					navigator={this.props.navigator}
    					initObj={{
    						backName:this.props.backName,
    						barTitle:this.props.title
    					}}/>
    				<WebView
    					startInLoadingState={true}
    					contentInset={{top:-44,bottom:-120}}
    					source={{uri:this.props.url}}/>
    			</View>
    		);
    	}
    });
    
    module.exports = CustomWebView;
    

      

    10.book_item.js

    /*
    	8.图书列表 item
    
    	实现功能:展示图书信息,点击item进入图书详情页面
    
    	包含组件:基本组件
    
    	外部传入:
    
    	book  图书对象
    	onPress事件处理方法  通过...this.props绑定,需要设置参数,即图书id
    
    	需要使用的字段:
    
    		image  图书缩略图
    		title  图书名称
    		publisher  出版社
    		author  作者
    		price  价格
    		pages  图书总页数
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	Image,
    	TouchableOpacity
    } from 'react-native';
    
    var BookItem = React.createClass({
    	render: function() {
    		var book = this.props.book;
    
    		return (
    			<TouchableOpacity style={styles.item} {...this.props}>
    				{/* 图书图像 */}
    				<View style={styles.imageContainer}>
    					<Image style={styles.image} source={{uri:book.image}}/>
    				</View>
    				{/* 图书信息 */}
    				<View style={styles.contentContainer}>
    					<View style={styles.textContainer}>
    						<Text numberOfLines={1}>{book.title}</Text>
    					</View>
    					<View style={styles.textContainer}>
    						<Text style={styles.publisher_author} numberOfLines={1}>{book.publisher}</Text>
    					</View>
    					<View style={styles.textContainer}>
    						<Text style={styles.publisher_author} numberOfLines={1}>{book.author}</Text>
    					</View>
    					<View style={{flexDirection:"row",flex:1,alignItems:"center"}}>
    						<Text style={styles.price}>{book.price}</Text>
    						<Text style={styles.pages}>{book.pages}页</Text>
    					</View>
    				</View>
    			</TouchableOpacity>
    		)
    	}
    });
    
    var styles = StyleSheet.create({
    	item: {
    		flexDirection: "row",
    		height: 120,
    		padding: 10
    	},
    	imageContainer: {
    		justifyContent: "center",
    		alignItems: "center"
    	},
    	image: {
    		 80,
    		height: 100
    	},
    	contentContainer: {
    		flex: 1,
    		marginLeft: 15
    	},
    	textContainer: {
    		flex: 1,
    		justifyContent: "center"
    	},
    	publisher_author: {
    		color: "#A3A3A3",
    		fontSize: 13
    	},
    	price: {
    		color: "#2BB2A3",
    		fontSize: 16
    	},
    	pages: {
    		marginLeft: 10,
    		color: "#A7A0A0"
    	}
    });
    
    module.exports = BookItem;
    

      

    11.book_list.js

    /*
    	9.图书列表模块:搜索栏、图书列表
    	图书列表的内容:通过调用图书搜索接口获得多条图书数据
    	图书列表Item是单独封装的
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	Image,
    	TouchableOpacity,
    	ListView,
    	ScrollView
    } from 'react-native';
    
    // 从common模块导入内容
    var Util = require("./../common/util");
    var SearchBar = require("./../common/searchBar");
    var ServiceURL = require("./../common/service");
    var BookItem = require("./book_item");
    var BookDetail = require("./book_detail");
    
    var BookList = React.createClass({
    	getInitialState: function() {
    		var ds = new ListView.DataSource({
    			rowHasChanged: (oldRow, newRow) => oldRow !== newRow
    		});
    
    		return {
    			// dataSource
    			dataSource: ds,
    			// 网络请求状态标识
    			show: false,
    			// 搜索关键字
    			// 作用:1.搜索接口需要设置搜索内容 2.点击搜索按钮时,修改关键字内容,重新请求数据,重新渲染
    			keywords: "react"
    		};
    	},
    	getData: function() {
    		// 开启loading,每次搜索时都需要重新下载显示数据
    		this.setState({
    			show: false
    		});
    
    		// 请求数据
    		var that = this;
    		var url = ServiceURL.book_search + "?count=20&q=" + this.state.keywords;
    
    		Util.getRequest(url, function(data) {
    			// 请求成功回调函数
    			/*
    				如果没有相关书籍,使用alert提示
    				https://api.douban.com/v2/book/search?count=20&q=react
    				{"count":0,"start":0,"total":0,"books":[]}
    			 */
    
    			if (!data.books || data.books.length == 0) {
    				return alert("未查询到相关书籍");
    			}
    
    			// 设置下载状态和数据源
    			var ds = new ListView.DataSource({
    				rowHasChanged: (oldRow, newRow) => oldRow !== newRow
    			});
    
    			that.setState({
    				show: true,
    				dataSource: ds.cloneWithRows(data.books)
    			});
    
    		}, function(error) {
    			// 请求失败回调函数
    			alert(error);
    		})
    	},
    	// TextInput的onChangeText事件处理方法
    	_changeText: function(text) {
    		this.setState({
    			keywords: text
    		});
    	},
    	_searchPress: function() {
    		this.getData();
    	},
    	_showDetail:function(bookID){
    		var detailRoute = {
    			component: BookDetail,
    			passProps:{
    				bookID: bookID
    			}
    		}
    
    		this.props.navigator.push(detailRoute);
    	},
    	// 布局
    	render: function() {
    		return (
    			<ScrollView>
    				<SearchBar
    					placeholder="请输入图书的名称"
    					onPress={this._searchPress}
    					onChangeText={this._changeText}/>
    				{
    					// 请求数据时显示loading,数据请求成功后显示ListView
    					this.state.show ?
    						<ListView
    							dataSource={this.state.dataSource}
    							initialListSize={10}
    							renderRow={this._renderRow}
    							renderSeparator={this._renderSeparator}/>
    					: Util.loading
    				}
    			</ScrollView>
    		);
    	},
    	componentDidMount: function() {
    		// 请求数据
    		this.getData();
    	},
    	_renderRow: function(book) {
    		return <BookItem book={book} onPress={this._showDetail.bind(this,book.id)}/>
    	},
    	// 分割线
    	_renderSeparator: function(sectionID: number, rowID: number) {
    		var style = {
    			height: 1,
    			backgroundColor: "#CCCCCC"
    		}
    
    		return <View style={style} key={sectionID+rowID} />
    	}
    });
    
    var styles = StyleSheet.create({
    	//
    });
    
    module.exports = BookList;
    

      

    12.book_detail.js

    /*
    	10.图书详情
    
    	实现功能:展示图书详情,包括:图书信息、图书简介、作者简介
    
    	包含组件:基本组件、BookItem(图书信息使用BookItem展示)
    
    	外部传入:
    
    	需要使用的字段:
    
    		image  图书缩略图
    		title  图书名称
    		publisher  出版社
    		author  作者
    		price  价格
    		pages  图书总页数
    		summary  图书简介
    		author_intro  作者简介
    */
    
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	Image,
    	ScrollView
    } from 'react-native';
    
    // 引入
    var ServiceURL = require("./../common/service");
    var Util = require("./../common/util");
    var Header = require("./../common/header");
    var BookItem = require("./book_item");
    
    // 创建组件类
    var BookDetail = React.createClass({
    	getInitialState:function() {
    		return {
    			bookData:null // 图书对象详情信息
    		}
    	},
    	getData:function(){
    		// 获取图书信息
    		var that = this;
    		var url = ServiceURL.book_detail_id + this.props.bookID;
    		Util.getRequest(url,function(data){
    			that.setState({
    				bookData:data
    			});
    		},function(error){
    			alert(error);
    		});
    	},
    	render:function(){
    		return (
    			<ScrollView style={styles.container}>
    				{
    					this.state.bookData ?
    						<View>
    							<Header
    								initObj={{backName:"图书",barTitle:this.state.bookData.title}}
    								navigator={this.props.navigator}/>
    							<BookItem book={this.state.bookData}/>
    							<View>
    								<Text style={styles.title}>图书简介</Text>
    								<Text style={styles.text}>{this.state.bookData.summary}</Text>
    							</View>
    							<View style={{marginTop:10}}>
    								<Text style={styles.title}>作者简介</Text>
    								<Text style={styles.text}>{this.state.bookData.author_intro}</Text>
    							</View>
    							<View style={{height:55}}></View>
    						</View>
    					: Util.loading
    				}
    			</ScrollView>
    		);
    	},
    	// 组件挂载以后,进行网络请求
    	componentDidMount:function(){
    		// 请求图书详情
    		this.getData();
    	}
    });
    
    var styles = StyleSheet.create({
    	container:{
    		flex:1,
    		backgroundColor:"white"
    	},
    	title:{
    		fontSize:16,
    		marginTop:10,
    		marginLeft:10,
    		marginBottom:10,
    		fontWeight:"bold"
    	},
    	text:{
    		marginLeft:10,
    		marginRight:10,
    		color:"#000D22"
    	}
    });
    
    module.exports = BookDetail;
    

      

    13.movie_item.js

    /*
    	11.电影列表item
    
    	实现功能:展示电影信息,点击item进入电影详情页面
    
    	包含组件:基本组件
    
    	外部传入:
    
    	movie  电影对象
    	onPress  通过...this.props绑定,需要设置参数:电影名称、电影详情页面url
    
    	需要使用的字段:
    		images.medium  电影图像
    		title  电影名称
    		casts  电影演员  数据需要再处理
    		rating.average  电影评分
    		year  电影上映时间
    		genres  电影标签
    		alt  电影详情url
    */
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	Image,
    	TouchableOpacity
    } from 'react-native';
    
    var MovieItem = React.createClass({
    	render:function() {
    		var movie = this.props.movie;
    
    		// 提取演员姓名
    		// 原始数据结构:数组元素是描述演员的对象,对象中包含演员名字
    		// 需要遍历数组,把每个演员的名字存在一个新的数组中
    		var actors = [];
    		for(var i in movie.casts){
    			actors.push(movie.casts[i].name);
    		}
    
    		return (
    			<TouchableOpacity style={styles.item} {...this.props}>
    				<View style={styles.imageContainer}>
    					<Image style={styles.image} resizeMode="contain" source={{uri:movie.images.medium}}/>
    				</View>
    				<View style={styles.contentContainer}>
    					<View style={styles.textContainer}>
    						<Text style={styles.text} numberOfLines={1}>名称:{movie.title}</Text>
    					</View>
    					<View style={styles.textContainer}>
    						<Text style={styles.text} numberOfLines={1}>演员:{actors}</Text>
    					</View>
    					<View style={styles.textContainer}>
    						<Text style={styles.text} numberOfLines={1}>评分:{movie.rating.average}</Text>
    					</View>
    					<View style={styles.textContainer}>
    						<Text style={styles.text} numberOfLines={1}>时间:{movie.year}</Text>
    					</View>
    					<View style={styles.textContainer}>
    						<Text style={styles.text} numberOfLines={1}>标签{movie.genres}</Text>
    					</View>
    				</View>
    			</TouchableOpacity>
    		);
    	}
    });
    
    var styles = StyleSheet.create({
    	item:{
    		flexDirection:"row",
    		height:120,
    		padding:10
    	},
    	imageContainer:{
    		justifyContent:"center",
    		alignItems:"center"
    	},
    	image:{
    		80,
    		height:110
    	},
    	contentContainer:{
    		flex:1,
    		marginLeft:15
    	},
    	textContainer:{
    		flex:1,
    		justifyContent:"center"
    	},
    	text:{
    		color:"black"
    	}
    });
    
    module.exports = MovieItem;
    

    14.movie_list.js

    /*
    	12.电影列表模块:搜索框、电影列表
    	电影列表的内容:通过调用电影搜索接口获得多条电影数据
    	电影列表Item是单独封装的
    */
    import React, { Component } from 'react';
    import {
    	AppRegistry,
    	StyleSheet,
    	Text,
    	View,
    	Image,
    	TouchableOpacity,
    	ListView,
    	ScrollView
    } from 'react-native';
    
    var SearchBar = require("./../common/searchBar");
    var Util = require("./../common/util");
    var ServiceURL = require("./../common/service");
    var MovieItem = require("./movie_item");
    var MovieWebView = require("./../common/customWebView");
    
    var MovieList = React.createClass({
    	getInitialState:function() {
    		var ds = new ListView.DataSource({
    			rowHasChanged:(oldRow,newRow) => oldRow!==newRow
    		});
    
    		return {
    			dataSource: ds,
    			show: false,
    			keywords:"哈利波特"
    		};
    	},
    	_changeText:function(text){
    		this.setState({
    			keywords:text
    		});
    	},
    	_searchPress:function(){
    		this.getData();
    	},
    	_showDetail:function(title,url){
    		var detailRoute = {
    			component:MovieWebView,
    			passProps:{
    				backName:"电影",
    				title:title,
    				url:url
    			}
    		};
    
    		// 推出
    		this.props.navigator.push(detailRoute);
    	},
    	getData:function(){
    		this.setState({
    			show:false
    		});
    
    		var that = this;
    		var url = ServiceURL.movie_search + "?count=20&q=" + this.state.keywords;
    
    		/*
    			https://api.douban.com/v2/movie/search?count=20&q=哈利波特
    			{"count":0,"start":0,"total":0,"books":[]}
    		 */
    
    		Util.getRequest(url,function(data){
    			if(!data.subjects||data.subjects.length==0){
    				return alert("未找到相关电影");
    			}
    
    			var ds = new ListView.DataSource({
    				rowHasChanged:(oldRow,newRow) => oldRow!==newRow
    			});
    
    			var movies = data.subjects;
    
    			that.setState({
    				show:true,
    				dataSource:ds.cloneWithRows(movies)
    			});
    		},function(error){
    			alert(error);
    		});
    
    	},
    	render:function(){
    		return (
    			<ScrollView>
    				<SearchBar
    					placeholder="请输入电影的名称"
    					onPress={this._searchPress}
    					onChangeText={this._changeText}/>
    				{
    					this.state.show ?
    						<ListView
    							dataSource={this.state.dataSource}
    							initialListSize={10}
    							renderRow={this._renderRow}
    							renderSeparator={this._renderSeparator}/>
    					: Util.loading
    				}
    			</ScrollView>
    		);
    	},
    	componentDidMount:function(){
    		// 请求数据
    		this.getData();
    	},
    	_renderRow:function(movie){
    		return <MovieItem movie={movie} onPress={this._showDetail.bind(this, movie.title, movie.alt)}/>;
    	},
    	// 分割线
    	_renderSeparator:function(sectionID:number,rowID:number){
    		var style = {
    			height: 1,
    			backgroundColor:"#CCCCCC"
    		};
    
    		return <View style={style} key={sectionID+rowID}></View>
    	}
    });
    
    var styles = StyleSheet.create({
    
    });
    
    module.exports = MovieList;
    

    15.效果图

  • 相关阅读:
    ILMerge将源DLL合并到目标EXE
    Nginx+redis的Asp.net
    JwtBearer认证
    Token认证登录以及权限控制
    ES索引
    Linux文本编辑器vim
    集群 安装 配置FastDFS
    When to use next() and return next() in Node.js
    spring-boot-starter-druid
    nodejs express
  • 原文地址:https://www.cnblogs.com/crazycode2/p/7146779.html
Copyright © 2020-2023  润新知