美文网首页
RN项目第二节 -- 首页实现

RN项目第二节 -- 首页实现

作者: 谦谦君子修罗刀 | 来源:发表于2018-05-25 07:31 被阅读277次

    一、微组件的封装

    每个页面的导航都会有不同的样式或者图片,为了实现代码的复用性,可以将导航统一封装成一个微小组件。
    封装的Item需要有可点击事件,需要显示文字和图片。

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

    再来分析每个页面都有不同的字体出现,比如说标题、段落、小标题。所以也可以将文字封装成单独的组件。

    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} />
    }
    
    //设置样式
    const styles = StyleSheet.create({
        h1: {
            fontSize: 15,
            fontWeight: 'bold',
            color: '#222222',
        },
        h2: {
            fontSize: 14,
            color: '#222222',
        },
        p: {
            fontSize: 13,
            color: '#777777',
        },
    });
    
    

    将整个页面分为两部分,页面最下方是一个列表,可以当成是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,
        },
    });
    

    在设置样式的时候,会用到全屏,因此可以把全屏幕的尺寸也封装起来。

    import { Dimensions, Platform, PixelRatio } from 'react-native'
    
    export default {
        width: Dimensions.get('window').width,
        height: Dimensions.get('window').height,
        onePixel: 1 / PixelRatio.get(),   //在iphone4+中代表一个像素点
        statusBarHeight: (Platform.OS === 'ios' ? 20 : 0)  //iOS平台状态栏默认为0,安卓平台默认为20
    }
    

    二、首页封装

    1) 首页导航的实现
    同样也是在navigationOptions调用箭头函数。返回标题、图片。当然左右两边可以返回已经封装好的NavigationItem属性。

    static navigationOptions = ({ navigation }) => ({
            headerTitle: (
                <TouchableOpacity style={styles.searchBar}>
                    <Image source={require('../../img/Home/search_icon.png')} style={styles.searchIcon} />
                    <Paragraph>一点点</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)列表的实现

    首页要实现列表功能,采用组件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并设置它的属性
    render() {
            return (
                <View style={styles.container}>
                    <FlatList
                        data={this.state.dataList}   //请求的数据
                        keyExtractor={this.keyExtractor} //设置每个item唯一的key
                        onRefresh={this.requestData}   //刷新的操作
                        refreshing={this.state.refreshing}   //刷新状态
                        ListHeaderComponent={this.renderHeader}  //头部页面展示
                        renderItem={this.renderCell}  //每个item
                    />
                </View>
            );
        }
    
    • 存放的数据要在state中声明并指定属性。(类中)
    state: {
            discounts: Array<Object>,
            dataList: Array<Object>,
            refreshing: boolean,
        }
    
    • 在构造函数中设置初始值,并绑定要实现的方法
    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. 实现方法
    • keyExtractor设置每个item唯一的key
    keyExtractor(item, index) {
            return item.id
        }
    
    • onRefresh对应的requestData方法做刷新的操作
      每次请求数据,都要进行刷新,所以刷新的状态要改为true。而且要刷新之后,要刷新折扣版块和列表版块的内容。为了代码简洁,将这两个功能封装成方法
    requestData() {
            //每次请求数据 都要进行刷新
            this.setState({ refreshing: true })
            //调用折扣
            this.requestDiscount()
            //调用推荐方法
            this.requestRecommend()
        }
    
    • 实现折扣模块的方法

    这里使用ES7的的异步线程语法。await表示紧跟在后面的表达式需要等待结果。也就是说当执行到awiat的时候,执行器将交给其他线程,等执行权返回再从暂停的地方往后执行。
    这里做的是请求数据的操作,用fetch函数传入api得到全部的折扣数据结果。然后再转化为json数据,接着把json中的data赋值给discounts数组。

     async requestDiscount() {
            try {
                let response = await fetch(api.discount)
                let json = await response.json()
                this.setState({ discounts: json.data })
            } catch (error) {
                alert('错误信息:'+error)
            }
        }
    
    • 实现推荐列表的方法


    上图是从API中的recommend的url解析出来的json数据。选取需要的数据。在代码中用fetch将数据解析成json格式,取出data集合中的数据传入箭头函数中,一一赋值给指定变量之后返回给数组dataList。如此一来,就可以用setState方法改变数组的数据。

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

    为了不影响渲染效果,可以将请求数据的方法放在componentDidMount方法中

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

    在iOS或者其他编程语言中,会采用各类框架来防止代码冗余。最常用的是MVC模式。在本项目中,为了返回列表,可以先将列表的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
        }
    });
    
    • 到首页中调用
      引入框架
    import GroupPurchaseCell from '../GroupPurchase/GroupPurchaseCell'
    

    将数据传给cell并调用

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

    实现cell的onPress方法

    onCellSelected(info) {
            //把状态栏的样式给成暗色
            StatusBar.setBarStyle('default', false)
            //跳转到详情页面,并把本页信息传递给详情页
            this.props.navigation.navigate('GroupPurchase', { info: info })
        }
    

    当点击cell的时候,导航会跳转到详情页面,那么就要把要跳转页面的名称传入到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中引用详情页,并把它加入到导航当中
    import GroupPurchaseScene from './scene/GroupPurchase/GroupPurchaseScene'
    
    
    const Navigator = StackNavigator(
        {
            Tab: { screen: Tab },  //框架的页面
            // Web: { screen: WebScene }, //webview的页面
            GroupPurchase: { screen: GroupPurchaseScene },//详情页
        },
    

    为了测试,先把首页的renderHeader()方法添加进去

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

    测试结果如下:


    点击详情页也能跳转


    • 首页导航实现
    static navigationOptions = ({ navigation }) => ({
            headerTitle: (
                <TouchableOpacity style={styles.searchBar}>
                    <Image source={require('../../img/Home/search_icon.png')} style={styles.searchIcon} />
                    <Paragraph>一点点</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个部分,一个是滚动的部分,另一个则是格子的部分。并且这两部分底部都有一个分割线。现在来封装这两个部分。
    先封装最上方的部分,新建一个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,
        }
    });
    

    现在来封装HomeMenuView

    这个View的主体是一个ScrollView和一个PageControl,当然RN中是没有特定的页面控制器的,所以该PageControl是需要自己封装的。把它放入widget组件中。

    现在考虑PageControl需要什么属性。属性可以用propTypes来规定,然而最近React组件已经把PropTypes组件移除了React库,所以需要引入prop-types。import PropTypes from 'prop-types';

    numberofPage:首先是各个组件能够分为多少页,这个是必须要传入的。规定为number类型。可以用isRequired来约束。
    currentPage:当前页用来控制亮点会出现在哪一页,number类型。
    hidesForSinglePage:当页面为1时,是否隐藏控制器,bool类型。
    pageIndicatorTintColor:控制器上点的颜色,string类型。
    currentPageIndicatorTintColor:当前亮点的颜色,string类型。
    indicatorSize:指示器的大小,规定为object类型,
    indicatorStyle:指示器的样式,它是View规定的类型,所以规定为View.propTypes.style类型
    currentIndicatorStyle:当前指示器的样式。同上
    onPageIndicatorPress:点击指示器的处理时间,func类型。

    引入头文件

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

    在类中规定属性类型

     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
        }
    

    给属性设置为默认值

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

    实现方法

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

    实现render方法

    render() {
    //解构赋值,取出所有的属性
            var { style, ...props } = this.props;
    //给指示器设置默认的属性,备用
            var defaultStyle = {
                height: this.props.indicatorSize.height
            };
    //设置每个小点的样式
            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
            });
    //创建一个数组,将小点添加到pages里面。
            var pages = [];
            for (var i = 0; i < this.props.numberOfPages; i++) {
                pages.push(i);
            }
         //页面隐藏设置为真并且页面长度<=1时,返回null,否则返回一个个的小点。
            return (
                this.props.hidesForSinglePage && pages.length <= 1 ? null : <View style={[styles.container, defaultStyle, style]}>
                
     {/*从小点的集合中取出每个点,如果是当前的点就返回当前点样式,否则返回普通样式*/}
                    {pages.map((el, i) => <TouchableWithoutFeedback key={i} onPress={this.onPageIndicatorPress.bind(this, i)}>
                            <View style={i == this.props.currentPage ? currentIndicatorStyle : indicatorStyle} />
                        </TouchableWithoutFeedback>
                    )}
                </View>
            )
        }
    

    现在可以做封装HomeMenuView的操作了
    先把render函数要返回的东西梳理清楚

    return (
     
      //scrollView里面要包含多个Item。将数组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,也就是每个设置好样式的items。
    在render方法的return方法之前,创建一个数组,该数组用来存放每个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)
                        }} />
                )
            )
            //创建一个menuViews数组,用来表示每一页
            let menuViews = []
            //像上取整得到页数
            let pageCount = Math.ceil(menuItems.length / 10)
    
            for (let i = 0; i < pageCount; i++) {
                //slice() 方法可从已有的数组中返回选定的元素。start和end,表示一页放十个
                let items = menuItems.slice(i * 10, i * 10 + 10)
                // 一整页的
                let menuView = (
                    <View style={styles.itemsView} key={i}>
                        {items}
                    </View>
                )
                //加入到所有页面的数组
                menuViews.push(menuView)
            }
            //此处是省略的return 在上面已经写了
            }
    

    上面return方法中要返回的PageControl要将currentPage传入进去,所以在MenuView应该先有一个状态机以便在用户滚动页面的时候实施修改。

     state: {
            currentPage: number
        }
    
        constructor(props) {
            super(props)
    
            this.state = {
                currentPage: 0
            }
        }
    

    实现滚动的方法

    onScroll(e) {
                //拿到x的偏移量
            let x = e.nativeEvent.contentOffset.x
                  //用偏移量/宽度得到当前页数
            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) {
                        //改变状态机
    
                this.setState({
                    currentPage: currentPage
                })
            }
        }
    

    设置样式

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

    设置样式

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

    接下来封装头部的第二部分
    原理同第一部分类似,建立第二个部分的js文件HomeGridView和第二部分的每一小项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,  //一行放两个,减去一个像素点
            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 {
        //设定一个数组,用来接收数据
        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加入进去

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

    到构造函数中绑定onGridSelected和onMenuSelected

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

    将这两个方法的原型写出来

    onGridSelected(index) {
    
        }
        onMenuSelected(index) {
            alert(index)
        }
    

    首页第一个界面完成,其余的页面放在之后讲解。

    相关文章

      网友评论

          本文标题:RN项目第二节 -- 首页实现

          本文链接:https://www.haomeiwen.com/subject/qoxyjftx.html