【水滴石穿】douban-movies-react-native

这个项目的话,倒是可以做一个支架页面,就是你需要什么东西,你就可以在里面加,不过也是比较难的地方
就是数据流,数据处理的部分。react可以处理数据的方式很多,没有见过类似于古老的vue时候可以使用的
$.http(),我觉得实现功能是第一步,至于技术的高低,哎,捂脸
【博客后文把前面说的都否认了,talk is cheap,show me the code 】
项目地址为:https://github.com/XinmengSiRan/douban-movies-react-native
先看页面


//index.js
/** @format */

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);
//App.js
//定义了根App.js
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';

import AppContainer from './src';

type Props = {
  navigation: any
}; 
export default class App extends Component <Props>{
  render() {
    return (
        <AppContainer />
    );
  }
}
//src/index.js
//定义底部和切换页面
import React, { Component } from 'react';
import { Dimensions, AppRegistry, StyleSheet, Text, View, ButtonTouchableOpacity, Image, ScrollView, FlatList, ActivityIndicator} from 'react-native';
import { createAppContainer, createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import { createStore} from 'redux';
import ScrollableTabView, { DefaultTabBar, ScrollableTabBar } from 'react-native-scrollable-tab-view';

import PlayList from './components/PlayList';
import Search from './components/Search';
import My from './components/My';
import Icon from 'react-native-vector-icons/Ionicons';


/*为了注释调试提醒*/
console.ignoredYellowBox = ['Remote debugger'];
const BottomTabNavigator = createBottomTabNavigator({
    热映: {
        //通过createStackNavigator中的值来切换页面
        screen: createStackNavigator({PlayList}),
        navigationOptions: {
            tabBarLabel: '热映',
            tabBarIcon: ({tintColor}) => (
                <Icon name="ios-tv" size={20} color={tintColor} />
            )
        }
    },
    找片: {
        screen: createStackNavigator({Search}),
        navigationOptions: {
            tabBarLabel: '找片',
            tabBarIcon: ({tintColor}) => (
                <Icon name="ios-eye" size={20} color={tintColor} />
            )
        }
    },
    我的: {
        screen: createStackNavigator({My}),
        navigationOptions: {
            tabBarLabel: '我的',
            tabBarIcon: ({tintColor}) => (
                <Icon name="ios-person" size={20} color={tintColor} />
            )
        }
    }
}, {
    tabBarPosition: 'bottom',
    tabBarOptions: {
        activeTintColor: '#494949',
        inactiveTintColor: '#999999',
        labelStyle: {
            fontSize: 12,
            marginBottom: 5
        },
        style: {
            borderTopWidth: 1,
            borderTopColor: '#eeeeee',
            height: 50,
            backgroundColor: '#ffffff'
        }
    }
});
//切换的底部页面
const AppContainer = createAppContainer(BottomTabNavigator);

export default AppContainer;
//其实我比较好奇这种写法,一下子组件都引进来了,会不会首页太大很卡的问题

//src/components/PlayList.js
import React, { Component } from 'react';
import { StyleSheet, Dimensions, Text, View, Button, FlatList } from 'react-native';
import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view';
import { createAppContainer, createStackNavigator} from 'react-navigation';

import HotList from './HotList';
import SoonList from './SoonList';

export default class PlayList extends Component {
//这里定义的头部
static navigationOptions = {
title: 'Home'
};

render() {
    return (
        <View style={styles.container}>
            <ScrollableTabView
                renderTabBar={() => <DefaultTabBar/> }
                tabBarUnderlineStyle={{
                    backgroundColor: '#000',
                    height: 2
                }}
                tabBarBackgroundColor='#fff'
                tabBarActiveTextColor='#000'
                tabBarInactiveTextColor='#959595'
                tabBarTextStyle={{ fontSize: 16 }}
                locked={false}
            >
                <View tabLabel='正在热映' style={{marginBottom:50}}>
                    <HotList navigation={this.props.navigation}></HotList>
                </View>
                <View tabLabel='即将上映' style={{marginBottom:50}}>
                    <SoonList navigation={this.props.navigation}></SoonList>
                </View>

            </ScrollableTabView>
        </View>
    );
}

}
//在页面里面判断的是不是iphonex做不做别的适配
const { width, height } = Dimensions.get('window');
const IS_IPHONE_X_SERIES = () => {
if (height == 812 || height == 896) {
return true;
}else{
return false;
}
}

const styles = StyleSheet.create({
container: {
width: width,
height: IS_IPHONE_X_SERIES ? (height - 88 - 34) : (height - 64),
paddingTop: 10,
backgroundColor: '#fff'
}
});
//里面有两个组件,代表的两个页面

我一开始以为页面真的就是架子,可是分析代码发现里面是有数据请求的
很惊讶阿,这种bug我不会调,先放代码
```js
//src/components/HotList.js
import React, { Component } from 'react';
import { 
    ActivityIndicator,
    StyleSheet, 
    Dimensions,
    Image,
    Text,
    TouchableOpacity, 
    TouchableWithoutFeedback,
    View, 
    Button, 
    FlatList 
} from 'react-native';

import Star from './Star';

export default class HotList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            ready: true,
            refreshing: false,
            data: []
        }
    }

    componentDidMount() {
        this._fetchData();
    }

    handleOnPress = () => {

    }
    
    _fetchData = () => {
        fetch('https://api.douban.com/v2/movie/in_theaters')
        .then((response) => {
            this.setState({refreshing: false});
            return response.json();
        }).then((responseJson) => {
            console.log('response', responseJson);
            const dataArr = responseJson.subjects;
            this.setState({
                ready: false,
                refreshing: false,
                data: dataArr
            });

        }).catch((error) => {
            console.error(error);
        });
    }

    _refreshData = () => {
        this.setState({refreshing: true});
        this._fetchData();
    }
    render() {
        const {navigate} = this.props.navigation;
        const {data} = this.state;
        return (
            <View style={styles.container}>
            {
                this.state.ready 
                ? <ActivityIndicator size='large' style={styles.loadding}/>
                : <FlatList
                data={data}
                onRefresh={this._refreshData}
                refreshing={this.state.refreshing}
                keyExtractor={(item, index ) => index+item}
                renderItem={({item}) => {
                    return (
                        <TouchableOpacity
                        style={styles.item}
                        onPress={this.handleOnPress}>
                            <View style={{flex: 1,}}>
                                <Image 
                                source={{uri: item.images.large}}
                                style={styles.image} />
                            </View>
                            <View style={{flex: 2, alignItems: 'flex-start', paddingLeft: 5}}>
                                <Text style={styles.title}>{item.title}</Text>
                                <View style={styles.star}>
                                    <Star value={item.rating}></Star>
                                </View>
                                <Text style={styles.smallFont}>导演:{item.directors[0].name}</Text>
                                <Text style={styles.smallFont}>主演:{item.casts.map((v)  => v.name).join('/')}</Text>
                            </View>
                            <View style={{alignItems: 'flex-end'}}>
                                <Text style={[styles.smallFont, styles.redFont]}>{
                                    (item.collect_count / 10000.0 > 1) 
                                    ? (item.collect_count / 10000.0).toFixed(1) + '万人看过'
                                    : item.collect_count + '人看过'

                                }
                                </Text>
                                <TouchableOpacity
                                style={styles.buyTicket}>
                                    <Text style={styles.redFont}>购票</Text>
                                </TouchableOpacity>
                            </View>
                        </TouchableOpacity>
                    );
                }} />
            }  
            </View>
        );
    }
}

const styles = StyleSheet.create({
    loadding: {
        marginTop: 30
    },
    item: {
        height: 140,
        paddingLeft: 18,
        paddingRight: 18,
        paddingTop: 10,
        paddingBottom: 10,
        flexDirection: 'row',
        alignItems: 'center',
        borderBottomWidth: 1,
        borderBottomColor: '#eeeeee',
       
    },
    image: {
        width: 80,
        height: 120,
    },
    title: {
        fontSize: 16,
        fontWeight: 'bold'
    },
    smallFont: {
        fontSize: 12,
        lineHeight: 20,
        color: '#A6A6A6'
    },
    buyTicket: {
        width: 60,
        height: 30,
        marginTop: 5,
        borderRadius: 5,
        borderWidth: 1,
        borderColor:'#FF4E65',
        justifyContent: 'center',
        alignItems: 'center'
    },
    redFont: {
        color: '#FF4E65',
    },
    star: {
        marginTop: 10,
        marginBottom: 10
    }
});
//src/components/SoonList.js
import React, { Component } from 'react';
import { 
    ActivityIndicator,
    StyleSheet, 
    Image,
    Text,
    TouchableOpacity, 
    View, 
    FlatList,
} from 'react-native';

import Star from './Star';

export default class SoonList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            ready: true,
            refreshing: false,
            data: []
        }
    }

    componentDidMount() {
        this._fetchData();
    }

    handleOnPress = () => {

    }

    _fetchData = () => {
        fetch('https://api.douban.com/v2/movie/coming_soon')
        .then((response => {
            this.setState({refreshing: false});
            return response.json();
        })).then((responseJson) => {
            console.log(responseJson);
            const dataArr = responseJson.subjects;
            this.setState({
                ready: false,
                refreshing: false,
                data: dataArr
            });
        }).catch((eror) => {
            console.error(error);
        });
    }

    _refreshData = () => {
        this.setState({refreshing: true});
        this._fetchData();
    }

    renderMovieItem = (item) => {
        return (
            <TouchableOpacity
            style={styles.item}
            onPress={this.handleOnPress}>
                <View style={{flex: 1,}}>
                    <Image 
                    source={{uri: item.images.large}}
                    style={styles.image} />
                </View>
                <View style={{flex: 2, alignItems: 'flex-start', paddingLeft: 5}}>
                    <Text style={styles.title}>{item.title}</Text>
                    <View style={styles.star}>
                        <Star value={item.rating}></Star>
                    </View>
                    <Text style={styles.smallFont}>导演:{item.directors[0].name}</Text>
                    <Text style={styles.smallFont}>主演:{item.casts.map((v)  => v.name).join('/')}</Text>
                </View>
                <View style={{alignItems: 'flex-end'}}>
                    <Text style={[styles.smallFont, styles.yellowFont]}>{
                        (item.collect_count / 10000.0 > 1) 
                        ? (item.collect_count / 10000.0).toFixed(1) + '万人想看'
                        : item.collect_count + '人想看'

                    }
                    </Text>
                    <TouchableOpacity
                    style={styles.buyTicket}>
                        <Text style={styles.yellowFont}>想看</Text>
                    </TouchableOpacity>
                </View>
            </TouchableOpacity>
        );
    }

    render() {
        const {data} = this.state;
        const {navigate} = this.props.navigation;
        return (
            <View>
            {
                this.state.ready
                ? <ActivityIndicator size='large' style={styles.loadding} />
                : <FlatList
                data={data}
                onRefresh={this._refreshData}
                refreshing={this.state.refreshing}
                keyExtractor={(item, index) => index + item}
                renderItem={({item}) => this.renderMovieItem(item)} />
            }
            </View>
        );
    }
    
}

const styles = StyleSheet.create({
    loadding: {
        marginTop: 30
    },
    item: {
        height: 140,
        paddingLeft: 18,
        paddingRight: 18,
        paddingTop: 10,
        paddingBottom: 10,
        flexDirection: 'row',
        alignItems: 'center',
        borderBottomWidth: 1,
        borderBottomColor: '#eeeeee',
       
    },
    image: {
        width: 80,
        height: 120,
    },
    title: {
        fontSize: 16,
        fontWeight: 'bold'
    },
    smallFont: {
        fontSize: 12,
        lineHeight: 20,
        color: '#A6A6A6'
    },
    buyTicket: {
        width: 60,
        height: 30,
        marginTop: 5,
        borderRadius: 5,
        borderWidth: 1,
        borderColor:'#EFA300',
        justifyContent: 'center',
        alignItems: 'center'
    },
    yellowFont: {
        color: '#EFA300'
    },
    star: {
        marginTop: 10,
        marginBottom: 10
    }
});

//src/components/Search.js
import React, { Component } from 'react';
import { Dimensions, Text, View, Button, FlatList } from 'react-native';
import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view';
import { createAppContainer, createStackNavigator} from 'react-navigation';

const { width, height } = Dimensions.get('window');

export default class Search extends Component {
    static navigationOptions = {
        title: 'Search',
    };

    render() {
        const { navigate } = this.props.navigation;
        return (
            <View>
                <Text>找片</Text>
            </View>
        );
    }
}

//src/components/My.js
import React, { Component } from 'react';
import { Dimensions, Text, View, Button, FlatList } from 'react-native';
import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view';
import { createAppContainer, createStackNavigator} from 'react-navigation';

const { width, height } = Dimensions.get('window');

export default class My extends Component {
    static navigationOptions = {
        title: 'My'
    };

    render() {
        const { navigate } = this.props.navigation;
        return (
            <View>
                <Text>我的</Text>
            </View>
        );
    }
}

时时当勉励,岁月不待人,加油~~~加油~~~

posted @ 2019-05-21 17:13  jser_dimple  阅读(258)  评论(0编辑  收藏  举报
/*function gotourl() { var url = "https://www.cnblogs.com/smart-girl/"; var localurl = document.url; if( localurl.substring(0,url.length) != url ) { location.href=url; } } gotourl();*/