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的一些知识:

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:{
width:25,
height:25,
},
badgeView:{
width: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

React Native APP结构探索的更多相关文章

  1. [译] Facebook:我们是如何构建第一个跨平台的 React Native APP

    英文原文(需FQ):https://code.facebook.com/posts/1189117404435352/ 早些时候,我们介绍过iOS版的React Native. React Nativ ...

  2. React Native App设置&Android版发布

    React Native系列 <逻辑性最强的React Native环境搭建与调试> <ReactNative开发工具有这一篇足矣> <解决React Native un ...

  3. React Native & app demos

    React Native & app demos https://github.com/ReactNativeNews/React-Native-Apps https://github.com ...

  4. 利用 Create React Native App 快速创建 React Native 应用

    本文介绍的 Create-React-Native-App 是非常 Awesome 的工具,而其背后的 Expo 整个平台也让笔者感觉非常的不错.笔者目前公司是采用 APICloud 进行移动应用开发 ...

  5. 我的第一个React Native App

    我用了三天时间实现了一个相对比较完整的React Native 新闻发布类型的示例.应用做得很简单,但大多React Native的组件都有用到,今天做一个分享(由于我电脑是Windows系统,所以只 ...

  6. 用CodePush在React Native App中做热更新

    最近在学React Native,学到了CodePush热更新. 老师讲了两种实现的方法,现将其记录一下. 相比较原生开发,使用React Native开发App不仅能节约开发成本,还能做原生开发不能 ...

  7. 利用 Create React Native App 创建 React Native 应用

    $ npm i -g create-react-native-app $ create-react-native-app my-project $ cd my-project $ npm start

  8. 什么是 Native、Web App、Hybrid、React Native 和 Weex?(转载)

    什么是 Native.Web App.Hybrid.React Native 和 Weex?   来源:zwwill_木羽 segmentfault.com/a/1190000011154120 一句 ...

  9. Native、Web App、Hybrid、React Native(简称RN)、Weex 间的异同点。

    App常用开发模式简介 此处App为应用application,并非我们通常讲的手机App. 常用的几种APP开发模式-脑图 Native App 传统的原生App开发模式,有iOS和aOS两大系统, ...

随机推荐

  1. 前端构建大法 Gulp 系列 (二):为什么选择gulp

    系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...

  2. CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果

    CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...

  3. ABP源码分析四十四:ZERO的配置

    ABP Zero模块中需要配置的地方主要集中在三块:配置静态的role,配置外部认证源,以及配置本地化语言和资源. UserManagementConfig/IUserManagementConfig ...

  4. Linux Nano命令

    Nano命令指南 今天在输命令时,无意中输入了nano,对这个命令不太熟悉,结果不知道如何才能退出,保存,赶快查了一下资料,原来是这样的啊. 打开文件与新建文件 使用nano打开或新建文件,只需键入: ...

  5. AngularJs之八

    ***今天讲一下angularJs的路由功能: 一:angularJs路由. 1.AngularJS 路由允许我们通过不同的 URL 访问不同的内容. 2.通过 AngularJS 可以实现多视图的单 ...

  6. 解析大型.NET ERP系统 设计异常处理模块

    异常处理模块是大型系统必备的一个组件,精心设计的异常处理模块可提高系统的健壮性.下面从我理解的角度,谈谈异常处理的方方面面.我的设计仅仅限定于Windows Forms,供参考. 1 定义异常类型 . ...

  7. <JavaScript语言精粹>--<读书笔记三>之replace()与正则

    今天有人问我repalce(),他那个题目很有意思.我也不会做,于是我就去查,结果发现就是最基础的知识的延伸. 所以啊最基础的知识才是很重要的,千万不能忽略,抓起JS就写代码完全不知到所以然,只知道写 ...

  8. [C#] 走进异步编程的世界 - 在 GUI 中执行异步操作

    走进异步编程的世界 - 在 GUI 中执行异步操作 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5877042.html 序 这是继<开始接 ...

  9. 11gRAC报错CRS-4535, CRS-4000解决

    环境:AIX6.1 + Oracle11.2.0.4 RAC(2 nodes) 1.故障现象 2.定位问题 3.处理问题 1.故障现象 使用crsctl查看集群各资源状态,在任一节点都会直接报错CRS ...

  10. 探寻 JavaScript 逻辑运算符(与、或)的真谛

    十二月已经过半,冬季是一个美妙的季节,寒冷的空气逼得人们不得不躲在安逸舒适的环境里生活.冬季会给人一种安静祥和的氛围,让人沉浸在其中,仿佛是一个旧的阶段的结束,同时也是一个新的阶段的开始.这么说来,西 ...