RN項(xiàng)目第二節(jié) -- 首頁實(shí)現(xiàn)

一、微組件的封裝

每個頁面的導(dǎo)航都會有不同的樣式或者圖片,為了實(shí)現(xiàn)代碼的復(fù)用性恕沫,可以將導(dǎo)航統(tǒng)一封裝成一個微小組件。
封裝的Item需要有可點(diǎn)擊事件纱意,需要顯示文字和圖片婶溯。

import React, { PureComponent } from 'react'
import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native'

export default class NavigationItem extends PureComponent {
    render() {
    // 圖片和文字時從外界傳入的 所以用到props
        let icon = this.props.icon &&
            <Image style={[styles.icon, this.props.iconStyle]} source={this.props.icon} />

        let title = this.props.title &&
            <Text style={[styles.title, this.props.titleStyle]}>{this.props.title}</Text>
        return (
            <TouchableOpacity style={styles.container} onPress={this.props.onPress}>
                {icon}
                {title}
            </TouchableOpacity>
        );
    }
}

// 樣式
const styles = StyleSheet.create({
    container: {
        flex:1,
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
    },
    icon: {
        width: 27,
        height: 27,
        margin: 8,
    },
    title: {
        fontSize: 15,
        color: '#333333',
        margin: 8,
    }
});

再來分析每個頁面都有不同的字體出現(xiàn),比如說標(biāo)題偷霉、段落迄委、小標(biāo)題。所以也可以將文字封裝成單獨(dú)的組件类少。

import React from 'react';
import ReactNative, { StyleSheet, Dimensions, Text ,ReactElement} from 'react-native'
import color from './color'

export function Heading1({style, ...props}) {
    return <Text style={[styles.h1, style]} {...props} />
}

export function Heading2({style, ...props}) {
    return <Text style={[styles.h2, style]} {...props} />
}

export function Paragraph({style, ...props}) {
    return <Text style={[styles.p, style]} {...props} />
}

//設(shè)置樣式
const styles = StyleSheet.create({
    h1: {
        fontSize: 15,
        fontWeight: 'bold',
        color: '#222222',
    },
    h2: {
        fontSize: 14,
        color: '#222222',
    },
    p: {
        fontSize: 13,
        color: '#777777',
    },
});

將整個頁面分為兩部分叙身,頁面最下方是一個列表,可以當(dāng)成是iOS中的tableView硫狞,而頁面上方可以看做是頭部的View信轿,這個View里面存放了各種模塊。模塊之間會有分割線残吩,可以將分割線也封裝成組件虏两。

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

import color from './color'

export default class SpacingView extends PureComponent {
    render() {
        return (
            <View style={styles.container}>
            </View>
        );
    }
}

// define your styles
const styles = StyleSheet.create({
    container: {
        height: 14,
        backgroundColor: color.background,
    },
});

在設(shè)置樣式的時候,會用到全屏世剖,因此可以把全屏幕的尺寸也封裝起來定罢。

import { Dimensions, Platform, PixelRatio } from 'react-native'

export default {
    width: Dimensions.get('window').width,
    height: Dimensions.get('window').height,
    onePixel: 1 / PixelRatio.get(),   //在iphone4+中代表一個像素點(diǎn)
    statusBarHeight: (Platform.OS === 'ios' ? 20 : 0)  //iOS平臺狀態(tài)欄默認(rèn)為0,安卓平臺默認(rèn)為20
}

二旁瘫、首頁封裝

1) 首頁導(dǎo)航的實(shí)現(xiàn)
同樣也是在navigationOptions調(diào)用箭頭函數(shù)祖凫。返回標(biāo)題、圖片酬凳。當(dāng)然左右兩邊可以返回已經(jīng)封裝好的NavigationItem屬性惠况。

static navigationOptions = ({ navigation }) => ({
        headerTitle: (
            <TouchableOpacity style={styles.searchBar}>
                <Image source={require('../../img/Home/search_icon.png')} style={styles.searchIcon} />
                <Paragraph>一點(diǎn)點(diǎn)</Paragraph>
            </TouchableOpacity>
        ),
        headerRight: (
            <NavigationItem
                icon={require('../../img/Home/icon_navigationItem_message_white.png')}
                onPress={() => {

                }}
            />
        ),
        headerLeft: (
            <NavigationItem
                title='福州'
                titleStyle={{ color: 'white' }}
                onPress={() => {

                }}
            />
        ),
        headerStyle: { backgroundColor: color.theme },
    })

2)列表的實(shí)現(xiàn)

首頁要實(shí)現(xiàn)列表功能,采用組件FlatList宁仔。

  • 引用必要的組件
import color from '../../widget/color'
import NavigationItem from '../../widget/NavigationItem'
import SpacingView from '../../widget/SpacingView'
import screen from '../../common/screen'
import api from '../../api'
import { Heading1, Heading2, Paragraph } from '../../widget/Text'
  • 在render方法中返回FlatList并設(shè)置它的屬性
render() {
        return (
            <View style={styles.container}>
                <FlatList
                    data={this.state.dataList}   //請求的數(shù)據(jù)
                    keyExtractor={this.keyExtractor} //設(shè)置每個item唯一的key
                    onRefresh={this.requestData}   //刷新的操作
                    refreshing={this.state.refreshing}   //刷新狀態(tài)
                    ListHeaderComponent={this.renderHeader}  //頭部頁面展示
                    renderItem={this.renderCell}  //每個item
                />
            </View>
        );
    }
  • 存放的數(shù)據(jù)要在state中聲明并指定屬性氛谜。(類中)
state: {
        discounts: Array<Object>,
        dataList: Array<Object>,
        refreshing: boolean,
    }
  • 在構(gòu)造函數(shù)中設(shè)置初始值霹娄,并綁定要實(shí)現(xiàn)的方法
constructor(props) {
        super(props)

        this.state = {
            discounts: [],
            dataList: [],
            refreshing: false,
        }

        { this.requestData = this.requestData.bind(this) }
        { this.renderCell = this.renderCell.bind(this) }
        { this.onCellSelected = this.onCellSelected.bind(this) }
        { this.keyExtractor = this.keyExtractor.bind(this) }
        { this.renderHeader = this.renderHeader.bind(this) }
        { this.onGridSelected = this.onGridSelected.bind(this) }
        { this.onMenuSelected = this.onMenuSelected.bind(this) }
    }
  1. 實(shí)現(xiàn)方法
  • keyExtractor設(shè)置每個item唯一的key
keyExtractor(item, index) {
        return item.id
    }
  • onRefresh對應(yīng)的requestData方法做刷新的操作
    每次請求數(shù)據(jù)驼侠,都要進(jìn)行刷新,所以刷新的狀態(tài)要改為true榨了。而且要刷新之后,要刷新折扣版塊和列表版塊的內(nèi)容攘蔽。為了代碼簡潔龙屉,將這兩個功能封裝成方法
requestData() {
        //每次請求數(shù)據(jù) 都要進(jìn)行刷新
        this.setState({ refreshing: true })
        //調(diào)用折扣
        this.requestDiscount()
        //調(diào)用推薦方法
        this.requestRecommend()
    }
  • 實(shí)現(xiàn)折扣模塊的方法

這里使用ES7的的異步線程語法。await表示緊跟在后面的表達(dá)式需要等待結(jié)果满俗。也就是說當(dāng)執(zhí)行到awiat的時候转捕,執(zhí)行器將交給其他線程,等執(zhí)行權(quán)返回再從暫停的地方往后執(zhí)行唆垃。
這里做的是請求數(shù)據(jù)的操作五芝,用fetch函數(shù)傳入api得到全部的折扣數(shù)據(jù)結(jié)果。然后再轉(zhuǎn)化為json數(shù)據(jù)辕万,接著把json中的data賦值給discounts數(shù)組枢步。

 async requestDiscount() {
        try {
            let response = await fetch(api.discount)
            let json = await response.json()
            this.setState({ discounts: json.data })
        } catch (error) {
            alert('錯誤信息:'+error)
        }
    }
  • 實(shí)現(xiàn)推薦列表的方法


上圖是從API中的recommend的url解析出來的json數(shù)據(jù)。選取需要的數(shù)據(jù)蓄坏。在代碼中用fetch將數(shù)據(jù)解析成json格式价捧,取出data集合中的數(shù)據(jù)傳入箭頭函數(shù)中丑念,一一賦值給指定變量之后返回給數(shù)組dataList涡戳。如此一來,就可以用setState方法改變數(shù)組的數(shù)據(jù)脯倚。

async requestRecommend(){
        try{
            let response = await fetch(api.recommend)
            let json = await response.json()
            let dataList = json.data.map(
                (info)=>{
                    return{
                        id:info.id,
                        imageUrl:info.squareimgurl,
                        title:info.mname,
                        subtitle:`$[{info.range}]${info.title}`,
                        price:info.price
                    }
                }
            )
            this.setState({
                dataList:dataList,
                refreshing:false,
            })
        }catch (error){
            this.setState({
                refreshing:false
            })
        }
    }

為了不影響渲染效果渔彰,可以將請求數(shù)據(jù)的方法放在componentDidMount方法中

componentDidMount() {
        this.requestData()
    }
  • 處理列表

在iOS或者其他編程語言中,會采用各類框架來防止代碼冗余推正。最常用的是MVC模式恍涂。在本項(xiàng)目中,為了返回列表植榕,可以先將列表的UI封裝起來再沧。

import React,{Component} from 'react'
import {View,Text,StyleSheet,TouchableOpacity,Image} from 'react-native'
import {Heading1,Paragraph}from '../../widget/Text'
import screen from '../../common/screen'
import color from '../../widget/color'
export default class GroupPurchaseCell extends Component{
    render(){
        let {info} = this.props
        let imageUrl = info.imageUrl.replace('w.h','160.0')
        return(
            <TouchableOpacity style={style.container} onPress = {()=>this.props.onPress(info)}>
                <Image source={{uri:imageUrl}} style={styles.icon}/>
                <View style={styles.rightContainer}>
                    <Heading1>{info.title}</Heading1>
                    <View>
                    </View>
                    <Paragraph numberOfLines={0} style={{ marginTop: 8 }}>{info.subtitle}</Paragraph>
                    <View style={{ flex: 1, justifyContent: 'flex-end' }}>
                        <Heading1 style={styles.price}>{info.price}元</Heading1>
                    </View>

                </View>
            </TouchableOpacity>
        )
    }
}
const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        padding: 10,
        borderBottomWidth: screen.onePixel,
        borderColor: color.border,
        backgroundColor: 'white',
    },
    icon: {
        width: 80,
        height: 80,
        borderRadius: 5,
    },
    rightContainer: {
        flex: 1,
        paddingLeft: 20,
        paddingRight: 10,
    },
    price: {
        color: color.theme
    }
});
  • 到首頁中調(diào)用
    引入框架
import GroupPurchaseCell from '../GroupPurchase/GroupPurchaseCell'

將數(shù)據(jù)傳給cell并調(diào)用

renderCell(info) {
        return (
            <GroupPurchaseCell
                info={info.item}
                onPress={this.onCellSelected}
            />
        )
    }

實(shí)現(xiàn)cell的onPress方法

onCellSelected(info) {
        //把狀態(tài)欄的樣式給成暗色
        StatusBar.setBarStyle('default', false)
        //跳轉(zhuǎn)到詳情頁面,并把本頁信息傳遞給詳情頁
        this.props.navigation.navigate('GroupPurchase', { info: info })
    }

當(dāng)點(diǎn)擊cell的時候,導(dǎo)航會跳轉(zhuǎn)到詳情頁面尊残,那么就要把要跳轉(zhuǎn)頁面的名稱傳入到navigate中炒瘸。

  • 為了測試,先簡單封裝詳情頁
    建立一個.js文件GroupPurchaseScene寝衫,用來測試
import React, { Component } from 'react'
import { View, Text, StyleSheet, ScrollView, TouchableOpacity, ListView, Image, InteractionManager } from 'react-native'

export default class GroupPurchaseScene extends Component {
    render(){
    return(
        <View>
            <Text>
                詳情頁面
            </Text>>
        </View>
    )
}
}
const Styles = StyleSheet.create({
    container: {
        flex:1,
        backgroundColor:'pink'
    }
})
  • 測試
    在RootScene中引用詳情頁顷扩,并把它加入到導(dǎo)航當(dāng)中
import GroupPurchaseScene from './scene/GroupPurchase/GroupPurchaseScene'

const Navigator = StackNavigator(
    {
        Tab: { screen: Tab },  //框架的頁面
        // Web: { screen: WebScene }, //webview的頁面
        GroupPurchase: { screen: GroupPurchaseScene },//詳情頁
    },

為了測試,先把首頁的renderHeader()方法添加進(jìn)去

renderHeader(){
        return(
            <View>
                <Text style={{fontSize:24}}>頭部啊頭部ddddddddddnihaoaha</Text>
            </View>
        )
    }

測試結(jié)果如下:


點(diǎn)擊詳情頁也能跳轉(zhuǎn)


  • 首頁導(dǎo)航實(shí)現(xiàn)
static navigationOptions = ({ navigation }) => ({
        headerTitle: (
            <TouchableOpacity style={styles.searchBar}>
                <Image source={require('../../img/Home/search_icon.png')} style={styles.searchIcon} />
                <Paragraph>一點(diǎn)點(diǎn)</Paragraph>
            </TouchableOpacity>
        ),
        headerRight: (
            <NavigationItem
                icon={require('../../img/Home/icon_navigationItem_message_white.png')}
                onPress={() => {

                }}
            />
        ),
        headerLeft: (
            <NavigationItem
                title='福州'
                titleStyle={{ color: 'white' }}
                onPress={() => {

                }}
            />
        ),
        headerStyle: { backgroundColor: color.theme },
    })
  • 添加樣式
searchBar: {
        width: screen.width * 0.7,
        height: 30,
        borderRadius: 19,
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'white',
        alignSelf: 'center',
    },
searchIcon: {
        width: 20,
        height: 20,
        margin: 5,
    }
  • 封裝頭部

頭部分為2個部分慰毅,一個是滾動的部分隘截,另一個則是格子的部分。并且這兩部分底部都有一個分割線。現(xiàn)在來封裝這兩個部分婶芭。
先封裝最上方的部分东臀,新建一個HomeMenuView.js。而這個部分又是由許多小的view組成的雕擂。所以將這些小的view也封裝起來啡邑。新建一個文件HomeMenuItem。而這個類返回的只要是一個圖片和文字即可井赌。

import React, {Component } from 'react'
import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native'
import { Heading2 } from '../../widget/Text'
import screen from '../../common/screen'
export default class HomeMenuItem extends Component{
    render(){
        return(
            <TouchableOpacity
                style={styles.container}
                onPress = {this.props.onPress}
            >
                <Image source={this.props.icon} resizeMode='contain' style={styles.icon}/>
                <Heading2>
                    {this.props.title}
                </Heading2>

            </TouchableOpacity>
        );
    }

}

const styles = StyleSheet.create({
    container: {
        justifyContent: 'center',
        alignItems: 'center',
        width: screen.width / 5,
        height: screen.width / 5,
    },
    icon: {
        width: screen.width / 9,
        height: screen.width / 9,
        margin: 5,
    }
});

現(xiàn)在來封裝HomeMenuView

這個View的主體是一個ScrollView和一個PageControl谤逼,當(dāng)然RN中是沒有特定的頁面控制器的,所以該P(yáng)ageControl是需要自己封裝的仇穗。把它放入widget組件中流部。

現(xiàn)在考慮PageControl需要什么屬性。屬性可以用propTypes來規(guī)定纹坐,然而最近React組件已經(jīng)把PropTypes組件移除了React庫枝冀,所以需要引入prop-types。import PropTypes from 'prop-types';

numberofPage:首先是各個組件能夠分為多少頁耘子,這個是必須要傳入的果漾。規(guī)定為number類型」仁模可以用isRequired來約束绒障。
currentPage:當(dāng)前頁用來控制亮點(diǎn)會出現(xiàn)在哪一頁,number類型捍歪。
hidesForSinglePage:當(dāng)頁面為1時户辱,是否隱藏控制器,bool類型糙臼。
pageIndicatorTintColor:控制器上點(diǎn)的顏色庐镐,string類型。
currentPageIndicatorTintColor:當(dāng)前亮點(diǎn)的顏色变逃,string類型必逆。
indicatorSize:指示器的大小,規(guī)定為object類型揽乱,
indicatorStyle:指示器的樣式名眉,它是View規(guī)定的類型,所以規(guī)定為View.propTypes.style類型
currentIndicatorStyle:當(dāng)前指示器的樣式锤窑。同上
onPageIndicatorPress:點(diǎn)擊指示器的處理時間璧针,func類型。

引入頭文件

import React, {Component } from 'react'
import { View, StyleSheet, TouchableWithoutFeedback } from 'react-native'
import assign from 'object-assign';
import PropTypes from 'prop-types';

在類中規(guī)定屬性類型

 static propTypes = {
        numberOfPages: PropTypes.number.isRequired,
        currentPage: PropTypes.number,
        hidesForSinglePage: PropTypes.bool,
        pageIndicatorTintColor: PropTypes.string,
        currentPageIndicatorTintColor: PropTypes.string,
        indicatorSize: PropTypes.object,
        indicatorStyle: View.propTypes.style,
        currentIndicatorStyle: View.propTypes.style,
        onPageIndicatorPress: PropTypes.func
    }

給屬性設(shè)置為默認(rèn)值

static defaultProps = {
        numberOfPages: 0,
        currentPage: 0,
        hidesForSinglePage: false,
        pageIndicatorTintColor: 'gray',
        currentPageIndicatorTintColor: 'white',
        indicatorSize: { width: 8, height: 8 },
        indicatorStyle: {},
        currentIndicatorStyle: {},
        onPageIndicatorPress: function () { }
    }

實(shí)現(xiàn)方法

 onPageIndicatorPress(index) {
        this.props.onPageIndicatorPress(index);
    }

實(shí)現(xiàn)render方法

render() {
//解構(gòu)賦值渊啰,取出所有的屬性
        var { style, ...props } = this.props;
//給指示器設(shè)置默認(rèn)的屬性探橱,備用
        var defaultStyle = {
            height: this.props.indicatorSize.height
        };
//設(shè)置每個小點(diǎn)的樣式
        var indicatorItemStyle = {
            width: this.props.indicatorSize.width,
            height: this.props.indicatorSize.height,
            borderRadius: this.props.indicatorSize.height / 2,
            marginLeft: 5,
            marginRight: 5
        };
//指示器整體樣式
        var indicatorStyle = assign({}, indicatorItemStyle, this.props.indicatorStyle, {
            backgroundColor: this.props.pageIndicatorTintColor
        });
//選中指示器的樣式
        var currentIndicatorStyle = assign({}, indicatorItemStyle, this.props.currentIndicatorStyle, {
            backgroundColor: this.props.currentPageIndicatorTintColor
        });
//創(chuàng)建一個數(shù)組申屹,將小點(diǎn)添加到pages里面。
        var pages = [];
        for (var i = 0; i < this.props.numberOfPages; i++) {
            pages.push(i);
        }
     //頁面隱藏設(shè)置為真并且頁面長度<=1時,返回null,否則返回一個個的小點(diǎn)隧膏。
        return (
            this.props.hidesForSinglePage && pages.length <= 1 ? null : <View style={[styles.container, defaultStyle, style]}>
            
 {/*從小點(diǎn)的集合中取出每個點(diǎn),如果是當(dāng)前的點(diǎn)就返回當(dāng)前點(diǎn)樣式,否則返回普通樣式*/}
                {pages.map((el, i) => <TouchableWithoutFeedback key={i} onPress={this.onPageIndicatorPress.bind(this, i)}>
                        <View style={i == this.props.currentPage ? currentIndicatorStyle : indicatorStyle} />
                    </TouchableWithoutFeedback>
                )}
            </View>
        )
    }

現(xiàn)在可以做封裝HomeMenuView的操作了
先把render函數(shù)要返回的東西梳理清楚

return (
 
  //scrollView里面要包含多個Item哗讥。將數(shù)組menuView添加到view里面
            <View style={styles.container}>
                <ScrollView contentContainerStyle={styles.contentContainer}
                    horizontal
                    showsHorizontalScrollIndicator={false}
                    pagingEnabled
                    onScroll={(e) => this.onScroll(e)}
                >
                    <View style={styles.menuContainer}>
                        {menuViews}
                    </View>
                </ScrollView>


                <PageControl
                    style={styles.pageControl}
                    numberOfPages={pageCount}
                    currentPage={this.state.currentPage}
                    hidesForSinglePage
                    pageIndicatorTintColor='gray'
                    currentPageIndicatorTintColor={color.theme}
                    indicatorSize={{ width: 8, height: 8 }}
                />
            </View>
        );

scrollview中包含的是menuView,也就是每個設(shè)置好樣式的items胞枕。
在render方法的return方法之前杆煞,創(chuàng)建一個數(shù)組,該數(shù)組用來存放每個item腐泻。

render() {
        //取出屬性中的menuinfos和onMenuSelected
        let { menuInfos, onMenuSelected } = this.props
        // 將屬性傳給每個HomeMenuitem
        let menuItems = menuInfos.map(
            (info, i) => (
                <HomeMenuItem
                    key={info.title}
                    title={info.title}
                    icon={info.icon}
                    onPress={() => {
                        onMenuSelected && onMenuSelected(i)
                    }} />
            )
        )
        //創(chuàng)建一個menuViews數(shù)組,用來表示每一頁
        let menuViews = []
        //像上取整得到頁數(shù)
        let pageCount = Math.ceil(menuItems.length / 10)

        for (let i = 0; i < pageCount; i++) {
            //slice() 方法可從已有的數(shù)組中返回選定的元素决乎。start和end,表示一頁放十個
            let items = menuItems.slice(i * 10, i * 10 + 10)
            // 一整頁的
            let menuView = (
                <View style={styles.itemsView} key={i}>
                    {items}
                </View>
            )
            //加入到所有頁面的數(shù)組
            menuViews.push(menuView)
        }
        //此處是省略的return 在上面已經(jīng)寫了
        }

上面return方法中要返回的PageControl要將currentPage傳入進(jìn)去,所以在MenuView應(yīng)該先有一個狀態(tài)機(jī)以便在用戶滾動頁面的時候?qū)嵤┬薷摹?/p>

 state: {
        currentPage: number
    }

    constructor(props) {
        super(props)

        this.state = {
            currentPage: 0
        }
    }

實(shí)現(xiàn)滾動的方法

onScroll(e) {
            //拿到x的偏移量
        let x = e.nativeEvent.contentOffset.x
              //用偏移量/寬度得到當(dāng)前頁數(shù)
        let currentPage = Math.round(x / screen.width)

        console.log('onScroll  ' + e.nativeEvent.contentOffset.x + '  page ' + currentPage + '  current ' + this.state.currentPage)
        if (this.state.currentPage != currentPage) {
                    //改變狀態(tài)機(jī)

            this.setState({
                currentPage: currentPage
            })
        }
    }

設(shè)置樣式

const styles = StyleSheet.create({
    container: {
        backgroundColor: 'white',
    },
    contentContainer: {
    },
    menuContainer: {
        flexDirection: 'row',
    },
    itemsView: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        width: screen.width,
    },
    pageControl: {
        margin: 10,
    }
});
  • 到首頁中修改readerHeader方法
    引入頭文件
import HomeMenuView from './HomeMenuView'

將HomeMenuView添加到方法中去

renderHeader() {
        return (
            <View>
                <HomeMenuView menuInfos={api.menuInfo} onMenuSelected={this.onMenuSelected} />
                <SpacingView />
                <View style={styles.recommendHeader}>
                    <Heading2>猜你喜歡</Heading2>
                </View>
            </View>
        )
    }

設(shè)置樣式

recommendHeader: {
        height: 35,
        justifyContent: 'center',
        borderWidth: screen.onePixel,
        borderColor: color.border,
        paddingVertical: 8,
        paddingLeft: 20,
        backgroundColor: 'white'
    },

接下來封裝頭部的第二部分
原理同第一部分類似,建立第二個部分的js文件HomeGridView和第二部分的每一小項(xiàng)HomeGridItem派桩。

HomeGridItem:

export default class HomeGridItem extends PureComponent {
    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')

        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>
        );
    }
}

// define your styles
const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        width: screen.width / 2 - screen.onePixel,  //一行放兩個,減去一個像素點(diǎn)
        height: screen.width / 4,
        backgroundColor: 'white',
        borderBottomWidth: screen.onePixel,
        borderRightWidth: screen.onePixel,
        borderColor: color.border
    },
    icon: {
        width: screen.width / 5,
        height: screen.width / 5,
    }
});

HomeGridView:

import React, { PureComponent } from 'react';
import { View, Text, StyleSheet } from 'react-native'
import color  from '../../widget/color'
import  screen from '../../common/screen'
import HomeGridItem from './HomeGridItem'

export default class HomeGridView extends PureComponent {
    //設(shè)定一個數(shù)組构诚,用來接收數(shù)據(jù)
    static defaultProps = {
        infos: []
    }

    render() {
        return (
            <View style={styles.container}>
            //將infos賦值給Item
                {this.props.infos.map((info, index) => (
                    <HomeGridItem
                        info={info}
                        key={index}
                        onPress={() => this.props.onGridSelected(index)} />
                ))}
            </View>
        );
    }
}

// define your styles
const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        justifyContent: 'space-between',
        borderTopWidth: screen.onePixel,
        borderLeftWidth: screen.onePixel,
        borderColor: color.border
    },
});

在HomeScene中
引入頭文件

import HomeGridView from './HomeGridView'

修改renderHeader方法,將gridView加入進(jìn)去

<HomeGridView infos={this.state.discounts} onGridSelected={(this.onGridSelected)} />
 <SpacingView />

到構(gòu)造函數(shù)中綁定onGridSelected和onMenuSelected

 { this.onGridSelected = this.onGridSelected.bind(this) }
        { this.onMenuSelected = this.onMenuSelected.bind(this) }

將這兩個方法的原型寫出來

onGridSelected(index) {

    }
    onMenuSelected(index) {
        alert(index)
    }

首頁第一個界面完成铆惑,其余的頁面放在之后講解范嘱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市员魏,隨后出現(xiàn)的幾起案子丑蛤,更是在濱河造成了極大的恐慌,老刑警劉巖撕阎,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件受裹,死亡現(xiàn)場離奇詭異,居然都是意外死亡闻书,警方通過查閱死者的電腦和手機(jī)名斟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門脑慧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魄眉,“玉大人,你說我怎么就攤上這事闷袒】勇桑” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵囊骤,是天一觀的道長晃择。 經(jīng)常有香客問我,道長也物,這世上最難降的妖魔是什么宫屠? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮滑蚯,結(jié)果婚禮上浪蹂,老公的妹妹穿的比我還像新娘抵栈。我一直安慰自己,他們只是感情好坤次,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布古劲。 她就那樣靜靜地躺著,像睡著了一般缰猴。 火紅的嫁衣襯著肌膚如雪产艾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天滑绒,我揣著相機(jī)與錄音闷堡,去河邊找鬼。 笑死疑故,一個胖子當(dāng)著我的面吹牛缚窿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播焰扳,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼倦零,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吨悍?” 一聲冷哼從身側(cè)響起扫茅,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎育瓜,沒想到半個月后葫隙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡躏仇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年恋脚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焰手。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡糟描,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出书妻,到底是詐尸還是另有隱情船响,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布躲履,位于F島的核電站见间,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏工猜。R本人自食惡果不足惜米诉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望篷帅。 院中可真熱鬧史侣,春花似錦汗销、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至李皇,卻和暖如春削茁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掉房。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工茧跋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卓囚。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓瘾杭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親哪亿。 傳聞我的和親對象是個殘疾皇子粥烁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件蝇棉、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,109評論 4 62
  • 再不寫讨阻,就忘記了。 前天上午忙了一陣子篡殷,回家休息钝吮,獨(dú)自一人,焦慮瞬間襲來板辽,擱在一邊兒奇瘦,睡覺。 醒來下午又繼續(xù)外出辦...
    李金峰_吉林閱讀 143評論 0 0
  • 項(xiàng)目管理步驟 1.需求評審:必須想盡辦法把整個需求流程串聯(lián)起來劲弦,形成總體認(rèn)識閉環(huán)2.接口層評審:想到每個場景下耳标,是...
    gadfly_only閱讀 721評論 0 49
  • “那我過來看看她吧!”軍在電話里回答這媽的話。他最怕我媽瓶您,直到婚后一直都怕麻捻。電話未掛纲仍,她媽問我要不要他過來呀袱,我點(diǎn)頭...
    娟娟頭閱讀 197評論 0 0
  • 下午3時,夏日太陽正毒郑叠,空氣中夾雜著車輛捲起的揚(yáng)塵夜赵,悶熱的天把市中心本來就快的節(jié)奏壓得更快了。 我買...
    慈開閱讀 268評論 3 1