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. [异常解决] JLINK 与STM32的SWD连接接线方式

    如果我们的板子上只留了4个接口:V3.3,SWDIO,SWDCLK,GND.那么和JTAG的连接关系参见下图: 注意缺口方向.然后GND可以接左边任何一个pin(除了最底下这个PIN). FROM: ...

  2. Azure 上通过 SendGrid 发送邮件

    SendGrid 是什么? SendGrid 是架构在云端的电子邮件服务,它能提供基于事务的可靠的电子邮件传递. 并且具有可扩充性和实时分析的能力.常见的用例有: 自动回复用户的邮件 定期发送信息给用 ...

  3. JS对象继承篇

    JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person() ...

  4. iOS-证书

    1.iOS-证书相关 2.iOS-证书申请 3.iOS-APNS证书申请与使用 4.iOS-App发布证书的申请与使用

  5. 了解HTML图像

    img <img>表示image图像,从技术上讲,<img>标签并不会在网页中插入图像,而是从网页上链接图像.<img> 标签创建的是被引用图像的占位空间. [必须 ...

  6. 从零开始编写自己的C#框架(19)——Web层后端权限模块

    不知不觉本系统写了快三个月了,最近写页面的具体功能时感觉到有点吃力,很多地方如果张嘴来讲的话可以说得很细,很全面,可写成文字的话,就不太会写了,有些地方想讲得清晰的话,得用多几倍的文字+实例+变化中的 ...

  7. EntityFramework.Extended 实现 update count+=1

    在使用 EF 的时候,EntityFramework.Extended 的作用:使IQueryable<T>转换为update table set ...,这样使我们在修改实体对象的时候, ...

  8. C# Word中设置/更改文本方向

    C# Word中设置/更改文本方向 一般情况下在Word中输入的文字都是横向的,今天给大家分享两种方法来设置/更改一个section内的所有文本的方向及部分文本的方向,有兴趣的朋友可以试下. 首先,从 ...

  9. PHP之封装一些常用的工具类函数

    分享一些PHP中常用的工具里函数: <?php /** * Created by PhpStorm. * User: Steven * Date: 2016/8/12 * Time: 14:21 ...

  10. Android之图片加载框架Fresco基本使用(二)

    PS:最近看到很多人都开始写年终总结了,时间过得飞快,又到年底了,又老了一岁. 学习内容: 1.进度条 2.缩放 3.ControllerBuilder,ControllerListener,Post ...