React Native项目实战之搭建美团个人中心界面

前端之家收集整理的这篇文章主要介绍了React Native项目实战之搭建美团个人中心界面前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

在很多app应用型APP中,个人中心往往会单独出一个模块,而对于刚入门React Native的朋友来说,怎么去实现一些静态的页面,并且怎么着手实现,怎么分层,怎么去实现这个架构,我想是很基础的(ps,本人新书,《React Native实战经典》定义国庆前后出版,欢迎大家捧场)。
首先,看一下实现的效果

项目讲解

首先,这是一个纯静态的页面包括顶部的个人介绍页面,已经下面的一个扩展页面。而下面扩展页面风格基本差不多,我们可以对其做一个简单的封装(MineItemCell.js),为了项目代码维护的方便,我们还可以将这些样式统一一下(text.js)。
text.js文字样式

  1. /** * https://github.com/facebook/react-native * @flow */
  2.  
  3. import React from 'react';
  4. import ReactNative,{ StyleSheet,Dimensions,Text,ReactElement} from 'react-native';
  5.  
  6. export function HeadingBig({style,...props}: Object): ReactElement {
  7. return <Text style={[styles.h0,style]} {...props} />
  8. }
  9.  
  10. export function Heading1({style,...props}: Object): ReactElement {
  11. return <Text style={[styles.h1,style]} {...props} />
  12. }
  13.  
  14. export function Heading2({style,...props}: Object): ReactElement {
  15. return <Text style={[styles.h2,style]} {...props} />
  16. }
  17.  
  18. export function Paragraph({style,...props}: Object): ReactElement {
  19. return <Text style={[styles.p,style]} {...props} />
  20. }
  21.  
  22. export function Tip({style,...props}: Object): ReactElement {
  23. return <Text style={[styles.tip,style]} {...props} />
  24. }
  25.  
  26. const styles = StyleSheet.create({
  27. h0: {
  28. fontSize: 40,color: '#06C1AE',},h1: {
  29. fontSize: 15,fontWeight: 'bold',color: '#222222',h2: {
  30. fontSize: 14,p: {
  31. fontSize: 13,color: '#777777',tip: {
  32. fontSize: 13,color: '#999999'
  33. }
  34. });

MineItemCell.js

  1. /** * Copyright (c) 2017-present,Liu Jinyong * All rights reserved. * * https://github.com/huanxsd/MeiTuan * @flow */
  2.  
  3. import React,{ Component } from 'react';
  4. import { View,StyleSheet,Image,TouchableOpacity } from 'react-native';
  5. import { Heading2,Paragraph } from './widght/Text'
  6. import Separator from './widght/Separator'
  7.  
  8. var Dimensions = require('Dimensions');
  9. var ScreenWidth = Dimensions.get('window').width;
  10.  
  11. class MineItemCell extends Component {
  12. render() {
  13. let icon = null;
  14. if (this.props.image) {
  15. icon = <Image style={styles.icon} source={this.props.image} />
  16. }
  17. return (
  18. <View style={styles.container}>
  19. <TouchableOpacity>
  20. <View style={[styles.content,this.props.style]}>
  21. {icon}
  22. <Heading2>{this.props.title}</Heading2>
  23. <View style={{ flex: 1,backgroundColor: 'blue' }} />
  24. <Paragraph style={{ color: '#999999' }}>{this.props.subtitle}</Paragraph>
  25. <Image style={styles.arrow} source={require('./image/icon_arrow.png')} />
  26. </View>
  27.  
  28. <Separator />
  29. </TouchableOpacity>
  30. </View>
  31. );
  32. }
  33. }
  34.  
  35. const styles = StyleSheet.create({
  36. container: {
  37. backgroundColor: 'white',content: {
  38. height: 44,flexDirection: 'row',alignItems: 'center',paddingLeft: 15,paddingRight: 10,icon: {
  39. width: 25,height: 25,marginRight: 10,subtitleContainer: {
  40. flexDirection: 'row',justifyContent: 'flex-end',arrow: {
  41. width: 14,height: 14,marginLeft: 5,}
  42. });
  43.  
  44. export default MineItemCell;

然后到界面的绘制了,首先绘制顶部个人资料部分:

  1. renderHeader() { return ( <View style={styles.header}> <View style={styles.topContainer}> <TouchableOpacity> <Image style={[styles.icon, {marginRight: 15}]} source={require('./image/icon_navigationItem_message_white.png')}/> </TouchableOpacity> <TouchableOpacity> <Image style={[styles.icon, {marginRight: 10}]} source={require('./image/icon_navigationItem_set_white.png')}/> </TouchableOpacity> </View> <View style={styles.userContainer}> <Image style={styles.avatar} source={require('./image/avatar.png')}/> <View> <View style={{flexDirection: 'row'}}> <Heading1 style={{color: 'white'}}>code_xzh</Heading1> <Image style={{marginLeft: 4}} source={require('./image/beauty_technician.png')}/> </View> <Paragraph style={{color: 'white',marginTop: 4}}>个人信息 ></Paragraph> </View> </View> </View> ) }

接着,我们在绘制下面的部分,由于下面部分我们队每个子视图做了封装,所以,我们可以这么做:通过getDataList()获取所有的值,进而绘制。
renderCells代码

  1. renderCells() {
  2. let cells = []
  3. let dataList = this.getDataList()
  4. for (let i = 0; i < dataList.length; i++) {
  5. let sublist = dataList[i]
  6. for (let j = 0; j < sublist.length; j++) {
  7. let data = sublist[j]
  8. let cell = <MineItemCell image={data.image} title={data.title} subtitle={data.subtitle}
  9. key={data.title}/>
  10. cells.push(cell)
  11. }
  12. cells.push(<SpacingView key={i}/>)
  13. }
  14.  
  15. return (
  16. <View style={{flex: 1}}>
  17. {cells}
  18. </View>
  19. )
  20. }

getDataList()代码

  1. getDataList() {
  2. return (
  3. [
  4. [
  5. {title: '我的钱包',subtitle: '办信用卡',image: require('./image/icon_mine_wallet.png')},{title: '余额',subtitle: '¥95872385',image: require('./image/icon_mine_balance.png')},{title: '抵用券',subtitle: '63',image: require('./image/icon_mine_voucher.png')},{title: '会员卡',subtitle: '2',image: require('./image/icon_mine_membercard.png')}
  6. ],[
  7. {title: '好友去哪',image: require('./image/icon_mine_friends.png')},{title: '我的评价',image: require('./image/icon_mine_comment.png')},{title: '我的收藏',image: require('./image/icon_mine_collection.png')},{title: '会员中心',subtitle: 'v15',image: require('./image/icon_mine_mineorder.png')},{title: '积分商城',subtitle: '好礼已上线',image: require('./image/icon_mine_member.png')}
  8. ],[
  9. {title: '客服中心',image: require('./image/icon_mine_service.png')},{title: '关于美团',subtitle: '我要合作',image: require('./image/icon_mine_about.png')}
  10. ]
  11. ]
  12. )
  13. }

页面完整代码

  1. /**
  2. * Sample React Native App
  3. * https://github.com/facebook/react-native
  4. * @flow ScrollView组件
  5. */
  6.  
  7. import React,{Component} from 'react';
  8. import {
  9. AppRegistry,RefreshControl,ScrollView,TouchableOpacity,View
  10. } from 'react-native';
  11. import { Heading1,Heading2,Paragraph } from './widght/Text'
  12. import MineItemCell from './MineItemCell';
  13. import SpacingView from './widght/SpacingView'
  14.  
  15. var Dimensions = require('Dimensions');
  16. var screenWidth = Dimensions.get('window').width;
  17. var screenHeight = Dimensions.get('window').height;
  18.  
  19.  
  20. class MineScene extends Component {
  21.  
  22. state: {
  23. isRefreshing: boolean
  24. }
  25.  
  26. constructor(props: Object) {
  27. super(props)
  28.  
  29. this.state = {
  30. isRefreshing: false
  31. }
  32. }
  33.  
  34. onHeaderRefresh() {
  35. this.setState({isRefreshing: true})
  36.  
  37. setTimeout(() => { this.setState({isRefreshing: false}) },2000); } renderCells() { let cells = [] let dataList = this.getDataList() for (let i = 0; i < dataList.length; i++) { let sublist = dataList[i] for (let j = 0; j < sublist.length; j++) { let data = sublist[j] let cell = <MineItemCell image={data.image} title={data.title} subtitle={data.subtitle} key={data.title}/> cells.push(cell) } cells.push(<SpacingView key={i}/>) } return ( <View style={{flex: 1}}> {cells} </View> ) } renderHeader() { return ( <View style={styles.header}> <View style={styles.topContainer}> <TouchableOpacity> <Image style={[styles.icon,{marginRight: 15}]} source={require('./image/icon_navigationItem_message_white.png')}/> </TouchableOpacity> <TouchableOpacity> <Image style={[styles.icon,{marginRight: 10}]} source={require('./image/icon_navigationItem_set_white.png')}/> </TouchableOpacity> </View> <View style={styles.userContainer}> <Image style={styles.avatar} source={require('./image/avatar.png')}/> <View> <View style={{flexDirection: 'row'}}> <Heading1 style={{color: 'white'}}>code_xzh</Heading1> <Image style={{marginLeft: 4}} source={require('./image/beauty_technician.png')}/> </View> <Paragraph style={{color: 'white',marginTop: 4}}>个人信息 ></Paragraph> </View> </View> </View> ) } getDataList() { return ( [ [ {title: '我的钱包',subtitle: '办信用卡',image: require('./image/icon_mine_wallet.png')},{title: '余额',subtitle: '95872385',image: require('./image/icon_mine_balance.png')},{title: '抵用券',subtitle: '63',image: require('./image/icon_mine_voucher.png')},{title: '会员卡',subtitle: '2',image: require('./image/icon_mine_membercard.png')} ],[ {title: '好友去哪',image: require('./image/icon_mine_friends.png')},{title: '我的评价',image: require('./image/icon_mine_comment.png')},{title: '我的收藏',image: require('./image/icon_mine_collection.png')},{title: '会员中心',subtitle: 'v15',image: require('./image/icon_mine_mineorder.png')},{title: '积分商城',subtitle: '好礼已上线',image: require('./image/icon_mine_member.png')} ],[ {title: '客服中心',image: require('./image/icon_mine_service.png')},{title: '关于美团',subtitle: '我要合作',image: require('./image/icon_mine_about.png')} ] ] ) } render() { return ( <View style={styles.container}> <View style={{ position: 'absolute',width: screenWidth,height: screenHeight / 2,backgroundColor: '#06C1AE' }}/> <ScrollView refreshControl={ <RefreshControl refreshing={this.state.isRefreshing} onRefresh={() => this.onHeaderRefresh()} tintColor='gray' /> }> {this.renderHeader()} <SpacingView /> {this.renderCells()} </ScrollView> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1,backgroundColor: '#f3f3f3',header: { backgroundColor: '#06C1AE',paddingBottom: 20 },topContainer: { flexDirection: 'row',marginTop: 7,icon: { width: 27,height: 27,userContainer: { flexDirection: 'row',margin: 10,avatar: { width: 50,height: 50,borderRadius: 25,borderWidth: 2,borderColor: '#51D3C6' } }); export default MineScene;

美团项目源码地址:react native美团项目源码

猜你在找的React相关文章