zoukankan      html  css  js  c++  java
  • React Native APP结构探索

    APP结构探索

    我在Github上找到了一个有登陆界面,能从网上获取新闻信息的开源APP,想来研究一下APP的结构。

    附上原网址:我的第一个React Native App

    具体来讲,就是研究一个复杂功能的APP在编写时是如何一步一步展开的,包括APP内部逻辑、与UI交互、与服务器交互等。

    index.android.js

    首先,我找到了index.android.js文件。文件很短,内容如下:

    /**
     * News
     * author : lufeng
     */
    
    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View
    } from 'react-native';
    
    var Route = require("./web_modules/route");
    
    AppRegistry.registerComponent('News', () => Route);
    
    

    可以看到,关键代码只有从"./web_modules/route"调用的Route,这也是整个程序的入口。

    route.js

    顺藤摸瓜找到了route.js,代码比之前长了一点,如下:

    /*
     * 页面路由
     */
    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      BackAndroid,
      Navigator,
      Image,
      Text,
      View,
      StatusBar
    } from 'react-native';
    
    var Tab = require("./tab");
    var _navigator;
    
    var Routes = React.createClass({
    
    	configureScence: function(){
    		return Navigator.SceneConfigs.FloatFromRight;
    	},
    	renderScene: function(route, navigator){
    		_navigator = navigator;
    		let Component = route.component;
    		return <Component route={route} navigator={navigator}/>
    	},
    	render: function(){
    		var renderScene = this.renderSceneAndroid;
    		var configureScence = this.configureScenceAndroid;
    		return (
    			<Navigator
    				initialRoute={{ name: '主页', component:Tab }}
    				configureScene={ this.configureScence }
    				renderScene={ this.renderScene}
    			/>
    		);
    	}
    });
    
    //监听硬件的back键操作
    BackAndroid.addEventListener('hardwareBackPress', function() {
    	if(_navigator == null){
    		return false;
    	}
    	if(_navigator.getCurrentRoutes().length === 1){
    		return false;
    	}
    	_navigator.pop();
    	return true;
    });
    
    module.exports = Routes;
    

    route.js文件里的结构仍然很清晰,主要有三部分:

    • 注册了名为Routes的组件。
    • 监听back键操作并进行相应处理。
    • 导出Routes

    React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。

    这里涉及到Navigator的一些知识:

    Navigator即导航器,通过导航器我们可以实现应用在不同的页面之间进行跳转。 
    导航器会建立一个路由栈,用来弹出,推入或者替换路由状态。该路由栈相当于Android原生中使用的任务栈

    renderScene

    renderScene方法就相当于我们使用的startActivity方法了,我们可以在该方法中设置需要渲染的场景(跳转的页面),该方法接收两个参数(必要参数),routenavigator,其中route就是路由的页面,navigator是一个Navigator对象,因为Navigator对象拥有poppushjump等方法,我们需要导航器对象来实现页面的跳转。而路由route需要我们提前进行配置。

    configureScene

    该方法用来设置指定路由对象的配置信息,从而改变场景的动画或者手势。如:

    configureScene={(route) => {
          //跳转的动画
          return Navigator.SceneConfigs.VerticalDownSwipeJump;
    }}
    

    initialRoute

    用来设置默认页面,也就是启动APP看到的第一个页面,需要两个参数,namecomponent

    可以看到,这里设置的默认页面来自Tab。而Tab来自"./tab",我们打开tab.js重头戏好像来了!!因为我看到了很多写页面的代码。。。

    tab.js

    先贴代码:

    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Image,
      Text,
      View,
      StatusBar
    } from 'react-native';
    
    import TabNavigator from 'react-native-tab-navigator'; //引入tabbar支持包  
      
    const TabNavigatorItem =TabNavigator.Item;  
    const TAB_ITEM = [{
    	code : 'Home',
    	name : '首页',
    	icon_n : require('./images/tab/tab_messagecenter_n.png'),
    	icon_p : require('./images/tab/tab_messagecenter_p.png'),
    	contentView : require('./tab_home')
    },{
    	code : 'Suggest',
    	name : '推荐',
    	icon_n : require('./images/tab/tab_contact_n.png'),
    	icon_p : require('./images/tab/tab_contact_p.png'),
    	contentView : require('./tab_suggest')
    },{
    	code : 'Find',
    	name : '发现',
    	icon_n : require('./images/tab/tab_discovery_n.png'),
    	icon_p : require('./images/tab/tab_discovery_p.png'),
    	contentView :  require('./tab_find')
    },{
    	code : 'Mine',
    	name : '我的',
    	icon_n : require('./images/tab/tab_myself_n.png'),
    	icon_p : require('./images/tab/tab_myself_p.png'),
    	contentView :  require('./tab_mine')
    }];
    
    class Tab extends Component {  
      
    	constructor(props){  
    		super(props);  
    		this.state = {  
    			items : TAB_ITEM,
    			selectedTab : TAB_ITEM[0].code
    		}  
    	}  
      
    	/*
    	 * tab点击方法 
    	 */  
    	onPress(tabCode){  
    		if(tabCode){  
    			this.setState({  
    				selectedTab : tabCode
    			});  
    		}  
    	}  
    	
        /*
         *渲染每项 
         */  
    	renderTabView(options){  
    		var tabNomal = options.icon_n;  
    		var tabPress = options.icon_p;  
     
    		return(  
    			<TabNavigatorItem  
    				key={options.code} 
    				title={options.name}  
    				renderIcon={()=><Image style={styles.tabIcon} source={tabNomal}/>}  
    				renderSelectedIcon={()=><Image style={styles.tabIcon} source={tabPress}/>}  
    				selected={this.state.selectedTab === options.code}  
    				selectedTitleStyle={{color:'#333333'}}  
    				onPress={()=>this.onPress(options.code)}  
    				renderBadge= {()=>options.badgeNum?<View style={styles.badgeView}>
    											<Text style={styles.badgeText}>options.badgeNum</Text>
    										  </View>:null}>  
    				<options.contentView route={this.props.route} navigator={this.props.navigator}/>
    			</TabNavigatorItem>  
    		);  
    	}  
        
    	render() {  
    	
    		var items = [];
            for (var i=0; i< this.state.items.length; i++) {
                items.push(this.renderTabView(this.state.items[i]));
            }
    		return (  
    			<View style={styles.container}>  
    				<TabNavigator tabBarStyle={styles.tab}>  
    					{items}
    				</TabNavigator>  
    			</View>  
    		);  
    	}  
    }  
      
    const styles = StyleSheet.create({  
      container: {  
        flex: 1,  
        backgroundColor: '#F5FCFF',  
      },    
      tab:{  
        height: 55,  
        alignItems:'center',  
        backgroundColor:'#f4f5f6',  
      },  
      tabIcon:{  
        25,  
        height:25,  
      },  
      badgeView:{  
        22,  
        height:14 ,  
        backgroundColor:'#f85959',  
        borderWidth:1,  
        marginLeft:10,  
        marginTop:3,  
        borderColor:'#FFF',  
        alignItems:'center',  
        justifyContent:'center',  
        borderRadius:8,  
      },  
      badgeText:{  
        color:'#fff',  
        fontSize:8,  
      }  
    });  
    
    module.exports = Tab;
    

    这里看的比较费力。。先是创建了一个名为tab的类,然后将界面底部的所有项的信息作为TAB_ITEM传到tabconstructor中。接着是onPress()方法作为tab的点击方法,后面的renderTabView方法的注释中标明了是渲染每项,其中又调用了TabNavigatorItem组件,这个组件来自Github。最后的render()里就是加载了整个布局。

    TabNavigator

    Tab组件(底部导航):react-native-tab-navigator

    https://github.com/exponentjs/react-native-tab-navigator

    TAB_ITEM

    这里以tab_home.js为例,其他的类似。核心代码如下:

    class Tab_Home extends Component { 
    	
    	constructor(props){  
    		super(props);  
    	}  
    	
    	showActionSheet(){
    		this.ActionSheet.show();
    	}
    	
    	render() {
    		return (
    			<View style={{flex:1,justifyContent:'flex-start',alignItems:'center', bottom : 5}}>  
    				<View style={styles.header}>  
    					<View style={styles.header_btn}></View>
    					<View style={styles.header_center}>
    						<Text style={styles.header_title}>新闻网</Text>
    					</View>
    					<TouchableOpacity  onPress={this.showActionSheet.bind(this)}>
    						<Image source={require('./images/header/more.png')} style={styles.header_icon,styles.header_btn}/>  
    					</TouchableOpacity>
    				</View>
    				<Swiper style={styles.wrapper} showsButtons={false} autoplay={false} height={200} showsPagination={true}>
    					<Image style={styles.slide} source={ require('./images/demo/slideshow1.jpg') }></Image>
    					<Image style={styles.slide} source={ require('./images/demo/slideshow2.jpg') }></Image>
    					<Image style={styles.slide} source={ require('./images/demo/slideshow3.jpg') }></Image>
    					<Image style={styles.slide} source={ require('./images/demo/slideshow4.jpg') }></Image>
    					<Image style={styles.slide} source={ require('./images/demo/slideshow5.jpg') }></Image>
    				</Swiper>
    				<List dataNums="6" route={this.props.route} navigator={this.props.navigator}/>
    				<ActionSheet 
                        ref={(o) => this.ActionSheet = o}
                        title="进入新闻推荐分类!"
                        options={buttons}
                        cancelButtonIndex={0}
                        destructiveButtonIndex={1}
                    />
    			</View>   
    		);
    	}
    }
    

    这个类主要是首页的布局,涉及到多种组件。其中比较值得一提的是TouchableOpacitySwiperActionSheet

    TouchableOpacity

    本组件用于封装视图,使其可以正确响应触摸操作。当按下的时候,封装的视图的不透明度会降低。这个过程并不会真正改变视图层级,大部分情况下很容易添加到应用中而不会带来一些奇怪的副作用。(译注:此组件与TouchableHighlight的区别在于并没有额外的颜色变化,更适于一般场景)

    这里此组件的onPress()事件的处理是弹出ActionSheet菜单。

    Swiper

    用于组件(常见的是图片)的轮播。

    官方文档:https://github.com/leecade/react-native-swiper

    ActionSheet

    从页面底部弹出菜单,拥有标题等属性,常用于应用的退出。本例是选择栏目用。(虽然没有实现具体的功能)

    官方文档:https://github.com/beefe/react-native-actionsheet

    今天就先到这啦。明天继续看~~

    感谢以下几篇博客:

    我的第一个React Native App

    Navigator

    ReactNative页面跳转Navigator

    React入门实例教程

    TouchableOpacity

  • 相关阅读:
    主成分分析PCA(1)
    机器人操作系统入门(七)rospy客户端库
    线性代数的本质(Essense of Linear Algebra)——3Blue1Brown
    机器人操作系统入门(六)roscpp客户端库
    《机器人操作系统(ROS)浅析》肖军浩译
    机器人操作系统入门(五)常用工具
    Python学习(八)Matlab和Numpy异同
    机器人操作系统入门(四)ROS通信架构
    机器人操作系统入门(三)ROS通信架构
    机器人操作系统入门(二)ROS文件系统
  • 原文地址:https://www.cnblogs.com/qingchanghan/p/5978969.html
Copyright © 2011-2022 走看看