React Native App

前端之家收集整理的这篇文章主要介绍了React Native App前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

XFood

这是我业余时间,自学RN时写的一个app

先看下效果图:

同时能运行在android跟ios设备,开发起来也很快,主要用到的知识有:

  • 自定义Button,titleBar,属性传值
  • 界面跳转Navigator
  • 菜谱列表ListView
  • 详情页需要滚动,使用ScrollView
  • 官方提供的Tabbar不能跨平台,第三方组件react-native-xtabbar的引入以及使用
  • 详情页的布局列表技巧
  • 方法调用,采用箭头表示法,没有使用Bind(this)

其他知识梳理:

  • 给组件包装导航Navigator实现跳转
import  Mainpager from  './Mainpager';

export default class XFoodMain extends Component {

    render() {
        var defaultName = 'Mainpager';
        var defaultComponent = Mainpager;
        return (
            <Navigator
                initialRoute={
                    {
                        name:defaultName,component: defaultComponent,}
                }
                configureScene={
                    ()=>{
                          return Navigator.SceneConfigs.HorizontalSwipeJump;
                    }
                }
                renderScene={

                    (route,navigator)=>{
                    let Com=route.component;
                    return <Com {...route.params}  navigator={navigator} />;
                }
                }>
            </Navigator>
        );
    }

说明:首先在XFoodMain这个类中想引入其他组件,就可以通过import Mainpager from './Mainpager';的方式引入,其中'./XXX'
表示在同一级目录,如果是上一级就可以这样表示:'../XXX'; Navigator组件的使用也入上所示,重要方法有3个,分别是初始化路由initialRoute、配置跳转时的动画configureScene、还有最后一个非常重要的方法renderScene,需要
注意的是,在返回Component的同时需要携带两个参数过去,即route.params、navigator。前者是在界面的跳转的时候可以传递参数,后者是来控制界面跳转以及返回

  • 这个界面只有一个按钮,点击进入Home主页
import  Button from '../../widget/Button';
import  AllKindsFood from '../allkindsFood/AllKindsFood';

export default class Mainpager extends Component {
    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            navigator: null,};
    }
    comeIn = () => {
        if(this.state.navigator){
            this.state.navigator.push({
                name: 'AllKindsFood',component: AllKindsFood,params: {
                    title: 'wtf',name: 'hehda',},})
        }

    };
    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    欢迎使用XFood
                </Text>
                <Button ref="button" text={"进入"} button_bg={"#1c4ef2"} onclick={this.comeIn}/>
            </View>
        );
    }
    componentDidMount() {
        var {navigator} =this.props;
        this.setState(
            this.state = {
            navigator: navigator,});
    }
}

在XFoodMain中已经给Mainpager包装导航了,所以在这里就可以通过var {navigator} =this.props;解构的方式拿到navigator,当点击按钮的时候,即可通过navigator push到下一个界面
在push的时候,可以携带以下参数,name、component、params。还有一点就是这里自定义的了按钮,并且给按钮自定义了一些属性,如text、button_bg、onclick方法等,在自定义的Button可以通过props拿到这些属性,即传入下去了

import TabBar from 'react-native-xtabbar';
import  HomeFoodPager from './HomeFoodPager';
import  TitleBar from '../../widget/TitleBar';

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

export default class AllKindsFood extends Component {
    // 构造
    constructor(props) {
        super(props);
        var {navigator,route}=this.props;
        // 初始状态
        this.state = {
            @H_404_207@navigator: navigator,};
    }
    render() {
        press = (index) => {
        };
        back = () => {
            var {navigator}=this.props;
            if (navigator != null) {
                navigator.pop();
            }
        };
        return (
            <View style={styles.container}>

                <TitleBar title="XFood" leftTitle="上一级" title_bg="#1c4ef2"/>
                <TabBar
                    style={styles.content}
                    onItemSelected={(index)=>press(index)}
                >
                    <TabBar.Item
                        icon={require('../../image/home_normal.png')}
                        selectedIcon={require('../../image/home_pressed.png')}
                        title='首页'>
                        <HomeFoodPager navigator={this.state.navigator}/>

                    </TabBar.Item>

                    <TabBar.Item
                        icon={require('../../image/find_normal.png')}
                        selectedIcon={require('../../image/find_pressed.png')}
                        title='其他'>
                        <HomeFoodPager navigator={this.state.navigator}/>

                    </TabBar.Item>

                </TabBar>
            </View>
        );
    }
}

TitleBar也是自定义的,跟前面的Button类型,都是自定义一些属性;紧接着是Tabbar,我是引用用第三方的,因为RN原有的组件是不支持跨平台的,引用方式:npm install [第三方库] –save ,如npm install react-native-device-info –save;
然后查看README文档,即可知道如何使用。在点击TabBar的Item时,需要将之前的navigator对象最为属性传递下去

  • 菜谱列表listview
import FoodDetail from './FoodDetial'; const Dimensions = require('Dimensions'); const {width} = Dimensions.get('window'); const {height} = Dimensions.get('window'); const foodJsonData = require('../data/foodData.json'); const ds = new ListView.DataSource({rowHasChanged: (r1,r2) => r1 !== r2}); const url = 'http://api.jisuapi.com/recipe/byclass?classid=2&start=0&num=10&appkey=019edfd7e2c45c72'; export default class HomeFoodPager extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { dataSource: ds.cloneWithRows(foodJsonData.result.list),}; } render() { pressItem = (rowData) => { const {navigator}=this.props; console.log(rowData.name); if(navigator!=null){ navigator.push({ name:"FoodDetail",component:FoodDetail,params:{ rowData:rowData,} }) } }; renderRowData = (rowData,rowID) => { return <TouchableOpacity @H_404_207@activeOpacity={0.5} @H_404_207@onPress={()=>pressItem(rowData)} > <View @H_404_207@style={styles.cellStyle}> <Image @H_404_207@style={{@H_301_305@width:100,@H_301_305@height:100}} @H_404_207@source={{@H_301_305@uri: @H_301_305@rowData.pic}}/> <View @H_404_207@style={styles.rightStyle}> <Text @H_404_207@style={{@H_301_305@fontWeight:'@H_301_305@bold'}} @H_404_207@numberOfLines={1} > {rowData.name }</Text> <Text @H_404_207@style={{@H_301_305@width:0@H_301_305@.7*@H_301_305@width,@H_301_305@textAlign: '@H_301_305@left',@H_301_305@fontWeight:'@H_301_305@normal',@H_301_305@marginTop:10} } @H_301_305@numberOfLines={3} > {@H_301_305@rowData.content }</Text> </View> </View> </TouchableOpacity> }; @H_301_305@return ( <@H_301_305@ListView @H_301_305@style={@H_301_305@styles.container} @H_301_305@dataSource={@H_301_305@this.state.dataSource} @H_301_305@renderRow={(@H_301_305@rowData,@H_301_305@rowID) => @H_301_305@renderRowData(@H_301_305@rowData,@H_301_305@rowID)} /> ) } //获取网络数据 @H_301_305@componentDidMount() { @H_301_305@fetch(@H_301_305@url)@H_301_305@.then((@H_301_305@response) => @H_301_305@response.json()) @H_301_305@.then((@H_301_305@responseJson) => { @H_301_305@var @H_301_305@jsonData = @H_301_305@responseJson.result.list; @H_301_305@console.log("数据大小:" +@H_301_305@responseJson); @H_301_305@this.setState( @H_301_305@this.state = { @H_301_305@dataSource: @H_301_305@ds.cloneWithRows(@H_301_305@jsonData),} ); }) @H_301_305@.catch((@H_301_305@error) => { @H_301_305@console.error(@H_301_305@error); }); } }

这个页面 主要是通过fetch请求网络数据,用listview展示数据列表,点击每个Item后将会传递rowData到详情页

  • 菜谱详情页
@H_404_207@const @H_404_207@Dimensions = @H_404_207@require('@H_404_207@Dimensions'); @H_404_207@const {@H_404_207@width} = @H_404_207@Dimensions.get('@H_404_207@window'); @H_404_207@export @H_404_207@default @H_404_207@class @H_404_207@FoodDetial @H_404_207@extends @H_404_207@Component { // 构造 @H_404_207@constructor(@H_404_207@props) { @H_404_207@super(@H_404_207@props); // 初始状态 @H_404_207@this.state = { @H_404_207@rowData: '',}; } @H_404_207@render() { @H_404_207@let @H_404_207@data = @H_404_207@this.state.rowData; @H_404_207@console.log(@H_404_207@data); @H_404_207@return ( <@H_404_207@View @H_404_207@style={styles.container}> <TitleBar @H_404_207@title="详情页" @H_404_207@leftTitle="上一级" @H_404_207@title_bg="#1c4ef2"/> <ScrollView> <View @H_404_207@style={styles.foodCeil}> <Text @H_404_207@style={{@H_301_305@backgroundColor:'#f2@H_301_305@c11@H_301_305@e',@H_301_305@color:'#fff',@H_301_305@paddingTop:5,@H_301_305@paddingBottom:5}}>菜肴名称</Text> <View @H_404_207@style={styles.foodheader}> <Image @H_404_207@style={styles.foodlogo} @H_404_207@source={{@H_301_305@uri:@H_301_305@data.pic}} @H_404_207@resizeMode={'stretch'}/> <Text @H_404_207@style={{@H_301_305@marginLeft:3}}>菜谱名称:{data.name}</Text> </View> <Text  @H_404_207@style={{@H_301_305@backgroundColor:'#f2@H_301_305@c11@H_301_305@e',@H_301_305@paddingBottom:5,@H_301_305@marginTop:4}}>菜肴说明</Text> <Text @H_404_207@style={{@H_301_305@backgroundColor:'#fff',@H_301_305@paddingBottom:5}}>类型:{data.tag}</Text> <Text  @H_404_207@style={{@H_301_305@backgroundColor:'#f2@H_301_305@c11@H_301_305@e',@H_301_305@marginTop:4}}>菜肴介绍</Text> <Text @H_404_207@style={{@H_301_305@backgroundColor:'#fff',@H_301_305@paddingBottom:5}}>介绍:{data.content}</Text> <Text  @H_404_207@style={{@H_301_305@backgroundColor:'#f2@H_301_305@c11@H_301_305@e',@H_301_305@marginTop:4}}>菜肴准备</Text> <Text @H_404_207@style={{@H_301_305@backgroundColor:'#fff',@H_301_305@paddingBottom:5}}>菜肴准备: {this.getData()}</Text> <Text  @H_404_207@style={{@H_301_305@backgroundColor:'#f2@H_301_305@c11@H_301_305@e',@H_301_305@marginTop:4}}>开始制作</Text> <View @H_404_207@style={styles.step}> {this.getStep()} </View> </View> </ScrollView> </View> ) } getStep=()=>{ var contentView =[]; let data = this.state.rowData; if (data.process != null) { for(let i=0;i<data.process.length;i++){  @H_404_207@contentView.push( <@H_404_207@View @H_404_207@key ={i} @H_404_207@style={styles.foodheader}> <Image @H_404_207@style={styles.foodlogo} @H_404_207@source={{@H_301_305@uri:@H_301_305@data.process[@H_301_305@i]@H_301_305@.pic}} @H_404_207@resizeMode={'stretch'}/> <Text @H_404_207@style={{@H_301_305@marginLeft:3,@H_301_305@width:@H_301_305@width*0@H_301_305@.6}} @H_404_207@numberOfLines={3} >第{i+1}步:{data.process[i].pcontent}</Text> </View> ) } return contentView; } }; getData = () => { let data = this.state.rowData; if (data.material != null) { var s = ''; for (let i = 0; i < @H_404_207@data.material.length; @H_404_207@i++) { @H_404_207@s += @H_404_207@data.material[@H_404_207@i]@H_404_207@.mname + "" + @H_404_207@data.material[@H_404_207@i]@H_404_207@.amount + ',\@H_404_207@t'; } @H_404_207@return @H_404_207@s; } }; @H_404_207@componentDidMount() { @H_404_207@const {@H_404_207@rowData}=this.props; @H_404_207@console.log(@H_404_207@rowData.name); @H_404_207@this.setState(@H_404_207@this.state = { @H_404_207@rowData: @H_404_207@rowData,}); } }

这个就是关于菜谱详情界面,可以看到我习惯于使用箭头函数方法的创建都是方法名=()=>{}这种方式,方法的引用可以()=>方法名(),括号中可以传入参数。这个界面其实有一个难点,就是每个菜谱的开始制作步骤数都不一样,可以看看getStep这个方法,我是通过创建一个数组,然后把每一个ceil都装进去,最后返回这个数组;还有getData()这个方法,注意这两者前面都加了一个不为null的判断,然后才取到数组的值

大概内容这么多,当然还有一些细节东西,比较适合初学者学习,喜欢的就下载看看吧!github

猜你在找的React相关文章