React Native项目组织结构介绍
代码组织:
目录结构:
.
├── components //组成应用的各个组件
│ ├── Routers.android.js //每个组件若实现不一样,分为android的实现和ios的实现。
│ ├── Routers.ios.js
│ ├── common //公共组件
│ ├── issues //议题页面
│ ├── navigation //导航组件,android用侧边栏,ios准备用tab
│ └── project //项目页面
└── network //网络服务
└── DataService.js
我自己的代码全部放在src目录下,这样写代码过程中搜索啊什么操作比较方便,从逻辑上也比较清晰。
react的应用,是用自定义组件或原生组件层层嵌套而成的。因此我将整个应用划分为组件部分(组成各个页面)和一些其他服务(目前比较简单,只抽象出发get请求的网络服务)。
components内,根据自己的业务逻辑进行抽象,把整个应用划分为层层嵌套的组件,目录结构的组织形式基本就是我页面的组织形式。如果有一些比较通用的功能,可以提取成公共组件,我放在common目录下。
每个组件如果ios和android的实现不太一样,则创建两个文件,如Routers.android.js和Routers.ios.js。
基本逻辑:
根组件:
我定义了一个Routers组件,作为整个app的根组件。Router组件实际上包装的官方的Navigator组件,主要作用:负责整个app的所有路由,当使用navigator去跳转路由时,会最终进入renderScene函数来渲染不同的页面。
提供了默认router,整个程序启动时,默认加载页面ProjectList。
各个页面:不同路由对应不同的页面,如Routers的renderScene函数中,每个if分支是一个页面。这些页面实际上就是一个个导出的组件。比如ProjectList组件是用来做项目列表的,但他自身又包含了一个用来渲染每个项目单元格的projectCell组件。如此,所有组件都是对上层呈现成一个统一的组件接口,对下层自己去组装多个不同组件,最终形成一个模块化的统一的app。
组件之间的关联:组件之间经常会发生关联。我自己用到了以下情况:
父改变子:
子通过state对外提供接口,父可以通过setState去改变子的状态,并让子重新渲染。state是React的一个很重要的概念。在组件上可以设一些属性,这些属性都有一个初始状态,然后用户的操作产生交互,只要是用setState去触发这个组件状态变化,则会触发这个组件重新渲染 UI 。
父直接调用子导出的方法,比如官方组件
DrawerLayoutAndroid提供的openDrawer方法。可以使用react的refs机制去调用。比如我在NavTab组件的openNavDrawer函数中,以this.refs['drawer'].openDrawer();这样的函数方式去调用。那么如何像这种方式导出自己的方法供父组件直接以函数方式调用?注意导出的方法必须是作为类方法就可以了,比如openNavDrawer这个函数就是导出给父用的。
子调用父:
这其实有点类似是反向依赖的设计模式。就是子提供触发回调的接口,但是究竟是触发后执行什么,子并不关心。比如我封装的NavToolbar(就是很多界面上面的工具条)组件的onClicked方法。很多地方的按钮都是返回上一级。 <NavToolbar ... onClicked={() => {this.props.nav.pop();}} /> 但是最底层的几个界面上的按钮,换成了弹出侧面导航条,以供切换。 <NavToolbar ... onClicked={this.onToolbarClicked} /> 对于这种情况,导航条要想抽象成公共的组件,他就不能依赖于他的父究竟是哪个界面。触发的具体动作就需要通过回调注入进来,这时就用这种方式。兄弟关系:
在共同的父中组合上面两种情况就可以了。比如ProjectList.android.js中onToolbarClicked: function (){ this.refs['navTab'].openNavDrawer(); }, <NavTab ref='navTab' nav={this.props.nav}> <NavToolbar icon={"ic_menu_white"} title={'项目'} onClicked={this.onToolbarClicked} /> {content} </NavTab>其他情况:
参考这篇文章,不过目前我还没用到这种毫无关系的事件触发,所以尚未研究。
调试
chrome调试:
安装react dev的chrome官方插件。在手机上设置host的ip,点击start chrome debugging。 chrome会自动跳转到调试地址,在浏览器上打开调试窗口,会发现里面多了一个react页签。inspect元素:在模拟器中打开inspect element面板,点击模拟器中的元素,chrome会跳转到对应dom。
槽点:
在浏览器改动css后,模拟器的布局不跟着更新。注意每个dom都有个RN的包裹,需要更改这个以RCT开头的包裹元素。参考issue。
浏览器的dom和手机上的元素位置对不准确。我有时会分不清哪个dom对应我屏幕哪一块。
调试经常失效,调试窗口的react页签动不动就找不到了,我大部分时候是直接改代码,在模拟器看效果的。
遇到的坑:
模拟器中的程序经常崩溃,代码语法有低级错误,一但
reload js,程序就有很大概率崩溃,需要react-native run-android重新开始。换工程运行项目,react-native run-android 前最好关下后台,否则两个项目会互相影响。
出错提示很不完善。
比如有时我会将<View>误写成<view>,或者忘记关闭标签。而这些低级错误,RN里面往往会非常难排除,提示往往都很奇怪,我都是靠走读代码发现。
比如有一次,我看了ECMAScript 6 Features的语法后,将DataService中var SERVER = 'http://www.yudianer.com/api';这句改成了const SERVER = 'http://www.yudianer.com/api';,当时没发现什么问题。但后面发现了奇怪的问题,只有在浏览器调试的时候,app才能正常运行,否则什么也不显示,而且没有任何提示。最后打包运行无数次都没反应,只能一点一点注释代码排除,才发现是我用了ECMAScript 6 Features,却没有配置。。。RN的有些组件有些限制,往往是后知后觉。例如:
DrawerLayoutAndroid这个组件外面不能再包一个
<View></View>。如果你不幸这么做了,会整个页面不显示了,而没有任何提示。。。如果ListView包在一个View中,那么外面这个View需要设置style={flex: 1}。否则ListView将不能滚动。
当遇到这种问题,最好去google一下,或去github看下有没有类似的议题。实在不行就通过注释代码的方法排除。
JSX的语法经常搞错,跟一般的模板语言不太一样。比如:
renderProject: function(project){
return(
<ProjectCell
onSelect={() => this.selectProject(project)}
project={project}/>
);
},
我会经常忘记这是个函数,而直接写成:
renderProject: function(project){
<ProjectCell
onSelect={() => this.selectProject(project)}
project={project}/>
},
这看上去没什么,问题是这种类似错误的提示很奇怪,不好定位。
总结:
RN在android上确实不太完善,调试工具,错误提示,文档等都不是很友好。但去学习下还是挺酷的,而且在facebook不遗余力的推动,相信会越来越完善的。
React Native项目组织结构介绍的更多相关文章
- Expo大作战(三)--针对已经开发过react native项目开发人员有针对性的介绍了expo,expo的局限性,开发时项目选型注意点等
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- 【腾讯Bugly干货分享】React Native项目实战总结
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...
- React Native 项目运行在 Web 浏览器上面
React Native 的出现,让前端工程师拥有了使用 JavaScript 编写原生 APP 的能力.相比之前的 Web app 来说,对于性能和用户体验提升了非常多. 但是 React Nati ...
- 使用Visual Studio Code和typescript 开发调试React Native项目
关于React Native的详细介绍我就不叙述了,他是使用js构建原声app的开发框架.一次变异多平台运行,非常强大.但是个人不喜欢js的过于灵活(弱类型)的语法.强大的强类型语言Typescrip ...
- React Native 项目实战-Tamic
layout: post title: React Native 项目实战 date: 2016-10-18 15:02:29 +0800 comments: true categories: Rea ...
- React Native 项目整合 CodePush 全然指南
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/y4x5M0nivSrJaY3X92c/article/details/81976844 作者 | 钱 ...
- 技术实践丨React Native 项目 Web 端同构
摘要:尽管 React Native 已经进入开源的第 6 个年头,距离发布 1.0 版本依旧是遥遥无期."Learn once, write anywhere",完全不影响 Re ...
- react native项目启动需要做的操作
一.启动: 1.查看端口(默认8081是否被占用) netstat -ano 可以查看所有的进程 2.netstat -ano | findstr "8081" 查看某个端口 ...
- React Native项目集成iOS原生模块
今天学习一下怎么在React Native项目中集成iOS原生模块,道理和在iOS原生项目中集成React Native模块类似.他们的界面跳转靠的都是iOS原生的UINavigationContro ...
随机推荐
- Oracle trunc()函数的用法及四舍五入 round函数
--Oracle trunc()函数的用法/**************日期********************/1.select trunc(sysdate) from dual --2011 ...
- Java 反射(二)
作者:郑剑锋链接:https://www.zhihu.com/question/24304289/answer/147529485来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...
- Spring利用反射调用接口
首先在项目中使用java反射调用 //根据实例及参数名获得方法A Method method = event.getObj().getClass() .getMethod(event.getMetho ...
- Mysql优化--Show Profile
Mysql 系列文章主页 =============== 是Mysql提供可以用来分析当前会话中语句执行的资源消耗情况.可以用于Sql的调优的测量.默认情况下处于关闭状态,并保存最近 15 次的运行结 ...
- GC其他:引用标记-清除、复制、标记-整理的说明
对象死亡历程 1.基本的mark&sweep是必须的,后续的都是对他的改进, 2.young代理的survivor就是使用了复制算法,避免碎片 3.还有标记整理算法(压缩),就是将存活的对象移 ...
- 利用生产者消费者模型和MQ模型写一个自己的日志系统-并发设计里一定会用到的手段
一:前言 写这个程序主要是用来理解生产者消费者模型,以及通过这个Demo来理解Redis的单线程取原子任务是怎么实现的和巩固一下并发相关的知识:这个虽然是个Demo,但是只要稍加改下Appender部 ...
- Win10 下Cmake编译配置 Opencv3.1 + Cuda7.5 + VS2013
折腾了三天终于配置成功了,在此写下编译配置的全部步骤和遇到的很多坑. 整体介绍: OpenCV 中 CUDA 实现的函数还不是太多,使用前要在OpenCV的官网上确认以下你想要的功能是否已经实现,否则 ...
- Node.js 字符串解码器
稳定性: 3 - 稳定 通过 require('string_decoder') ,可以使用这个模块.字符串解码器(StringDecoder)将缓存(buffer)解码为字符串.这是 buffer. ...
- 炫酷:一句代码实现标题栏、导航栏滑动隐藏。ByeBurger库的使用和实现
本文已授权微信公众号:鸿洋(hongyangAndroid)原创首发. 其实上周五的时候已经发过一篇文章.基本实现了底部导航栏隐藏的效果.但是使用起来可能不是很实用.因为之前我实现的方式是继承了系统的 ...
- PGM:部分观测数据
http://blog.csdn.net/pipisorry/article/details/52599451 基础知识 数据缺失的三种情形: 数据的似然和观测模型 Note: MLE中是将联合概率P ...