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. Spark笔记:复杂RDD的API的理解(上)

    本篇接着讲解RDD的API,讲解那些不是很容易理解的API,同时本篇文章还将展示如何将外部的函数引入到RDD的API里使用,最后通过对RDD的API深入学习,我们还讲讲一些和RDD开发相关的scala ...

  2. EasyPR--开发详解(5)颜色定位与偏斜扭转

    本篇文章介绍EasyPR里新的定位功能:颜色定位与偏斜扭正.希望这篇文档可以帮助开发者与使用者更好的理解EasyPR的设计思想. 让我们先看一下示例图片,这幅图片中的车牌通过颜色的定位法进行定位并从偏 ...

  3. asp.net pipeline完整图

  4. ASP.NET MVC 视图(二)

    ASP.NET MVC 视图(二) 前言 上篇中对于视图引擎只是做了简单的演示,对于真正的理解视图引擎的工作过程可能还有点模糊,本篇将会对由MVC框架提供给我们的Razor视图引擎的整个执行过程做一个 ...

  5. UniversalImageLoader的一个小问题

    最近在使用UniversalImageLoader时遇到了一个小问题,多个地方同时通过ImageLoader.getInstance().loadImage(url, new ImageSize(dp ...

  6. 计算机程序的思维逻辑 (44) - 剖析TreeSet

    41节介绍了HashSet,我们提到,HashSet有一个重要局限,元素之间没有特定的顺序,我们还提到,Set接口还有另一个重要的实现类TreeSet,它是有序的,与HashSet和HashMap的关 ...

  7. nginx源码分析之hash的实现

    nginx实现了自己的hash数据结构,正如数据结构中讲述的那样,nginx用开放链表法解决冲突,不过不同的是一旦一个hash表被初始化后就不会被修改,即插入和删除,只进行查询操作,所以nginx通过 ...

  8. CSS3与页面布局学习总结(一)——概要、选择器、特殊性与刻度单位

    web前端开发者最最注的内容是三个:HTML.CSS与JavaScript,他们分别在不同方面发挥自己的作用,HTML实现页面结构,CSS完成页面的表现与风格,JavaScript实现一些客户端的功能 ...

  9. 《HelloGitHub月刊》第09期

    <HelloGitHub>第09期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 前言 转眼就到年底了,月刊做到了第09期,感谢大家一路的支持和帮助

  10. 在idea中maven项目jdk编译version总是跳到1.5

    bug描述 项目ide: idea 项目构建工具:maven bug现象:每次修改pom之后,idea自动扫描一遍,然后发现默认的compile级别跳到5.0. 每次手动去setting里修改comp ...