代码组织:

目录结构:

  1. .
  2. ├── components //组成应用的各个组件
  3.    ├── Routers.android.js //每个组件若实现不一样,分为android的实现和ios的实现。
  4.    ├── Routers.ios.js
  5.    ├── common //公共组件
  6.    ├── issues //议题页面
  7.    ├── navigation //导航组件,android用侧边栏,ios准备用tab
  8.    └── project //项目页面
  9. └── network //网络服务
  10. └── DataService.js
  1. 我自己的代码全部放在src目录下,这样写代码过程中搜索啊什么操作比较方便,从逻辑上也比较清晰。

  2. react的应用,是用自定义组件或原生组件层层嵌套而成的。因此我将整个应用划分为组件部分(组成各个页面)和一些其他服务(目前比较简单,只抽象出发get请求的网络服务)。

  3. components内,根据自己的业务逻辑进行抽象,把整个应用划分为层层嵌套的组件,目录结构的组织形式基本就是我页面的组织形式。如果有一些比较通用的功能,可以提取成公共组件,我放在common目录下。

  4. 每个组件如果ios和android的实现不太一样,则创建两个文件,如Routers.android.js和Routers.ios.js。

基本逻辑:

  1. 根组件:
    我定义了一个Routers组件,作为整个app的根组件。Router组件实际上包装的官方的Navigator组件,主要作用:

    • 负责整个app的所有路由,当使用navigator去跳转路由时,会最终进入renderScene函数来渲染不同的页面。

    • 提供了默认router,整个程序启动时,默认加载页面ProjectList。

  2. 各个页面:不同路由对应不同的页面,如Routers的renderScene函数中,每个if分支是一个页面。这些页面实际上就是一个个导出的组件。比如ProjectList组件是用来做项目列表的,但他自身又包含了一个用来渲染每个项目单元格的projectCell组件。如此,所有组件都是对上层呈现成一个统一的组件接口,对下层自己去组装多个不同组件,最终形成一个模块化的统一的app。

  3. 组件之间的关联:组件之间经常会发生关联。我自己用到了以下情况:

    • 父改变子:

      • 子通过state对外提供接口,父可以通过setState去改变子的状态,并让子重新渲染。state是React的一个很重要的概念。在组件上可以设一些属性,这些属性都有一个初始状态,然后用户的操作产生交互,只要是用setState去触发这个组件状态变化,则会触发这个组件重新渲染 UI 。

      • 父直接调用子导出的方法,比如官方组件DrawerLayoutAndroid提供的openDrawer方法。可以使用react的refs机制去调用。比如我在NavTab组件的openNavDrawer函数中,以this.refs['drawer'].openDrawer();这样的函数方式去调用。那么如何像这种方式导出自己的方法供父组件直接以函数方式调用?注意导出的方法必须是作为类方法就可以了,比如openNavDrawer这个函数就是导出给父用的。

    • 子调用父:
      这其实有点类似是反向依赖的设计模式。就是子提供触发回调的接口,但是究竟是触发后执行什么,子并不关心。比如我封装的NavToolbar(就是很多界面上面的工具条)组件的onClicked方法。

      1. 很多地方的按钮都是返回上一级。
      2. <NavToolbar ... onClicked={() => {this.props.nav.pop();}} />
      3. 但是最底层的几个界面上的按钮,换成了弹出侧面导航条,以供切换。
      4. <NavToolbar ... onClicked={this.onToolbarClicked} />
      5. 对于这种情况,导航条要想抽象成公共的组件,他就不能依赖于他的父究竟是哪个界面。触发的具体动作就需要通过回调注入进来,这时就用这种方式。
    • 兄弟关系:
      在共同的父中组合上面两种情况就可以了。比如ProjectList.android.js

      1. onToolbarClicked: function (){
      2. this.refs['navTab'].openNavDrawer();
      3. },
      4. <NavTab ref='navTab' nav={this.props.nav}>
      5. <NavToolbar icon={"ic_menu_white"} title={'项目'} onClicked={this.onToolbarClicked} />
      6. {content}
      7. </NavTab>
    • 其他情况:
      参考这篇文章,不过目前我还没用到这种毫无关系的事件触发,所以尚未研究。

调试

  1. chrome调试:
    安装react dev的chrome官方插件。在手机上设置host的ip,点击start chrome debugging。 chrome会自动跳转到调试地址,在浏览器上打开调试窗口,会发现里面多了一个react页签。

  2. inspect元素:在模拟器中打开inspect element面板,点击模拟器中的元素,chrome会跳转到对应dom。

  3. 槽点:

    • 在浏览器改动css后,模拟器的布局不跟着更新。注意每个dom都有个RN的包裹,需要更改这个以RCT开头的包裹元素。参考issue

    • 浏览器的dom和手机上的元素位置对不准确。我有时会分不清哪个dom对应我屏幕哪一块。

    • 调试经常失效,调试窗口的react页签动不动就找不到了,我大部分时候是直接改代码,在模拟器看效果的。

遇到的坑:

  1. 模拟器中的程序经常崩溃,代码语法有低级错误,一但reload js,程序就有很大概率崩溃,需要react-native run-android重新开始。

  2. 换工程运行项目,react-native run-android 前最好关下后台,否则两个项目会互相影响。

  3. 出错提示很不完善。
    比如有时我会将<View>误写成<view>,或者忘记关闭标签。而这些低级错误,RN里面往往会非常难排除,提示往往都很奇怪,我都是靠走读代码发现。
    比如有一次,我看了ECMAScript 6 Features的语法后,将DataServicevar SERVER = 'http://www.yudianer.com/api';这句改成了const SERVER = 'http://www.yudianer.com/api';,当时没发现什么问题。但后面发现了奇怪的问题,只有在浏览器调试的时候,app才能正常运行,否则什么也不显示,而且没有任何提示。最后打包运行无数次都没反应,只能一点一点注释代码排除,才发现是我用了ECMAScript 6 Features,却没有配置。。。

  4. RN的有些组件有些限制,往往是后知后觉。例如:

    • DrawerLayoutAndroid这个组件外面不能再包一个<View></View>。如果你不幸这么做了,会整个页面不显示了,而没有任何提示。。。

    • 如果ListView包在一个View中,那么外面这个View需要设置style={flex: 1}。否则ListView将不能滚动。

    • 当遇到这种问题,最好去google一下,或去github看下有没有类似的议题。实在不行就通过注释代码的方法排除。

  5. JSX的语法经常搞错,跟一般的模板语言不太一样。比如:

  1. renderProject: function(project){
  2. return(
  3. <ProjectCell
  4. onSelect={() => this.selectProject(project)}
  5. project={project}/>
  6. );
  7. },

我会经常忘记这是个函数,而直接写成:

  1. renderProject: function(project){
  2. <ProjectCell
  3. onSelect={() => this.selectProject(project)}
  4. project={project}/>
  5. },

这看上去没什么,问题是这种类似错误的提示很奇怪,不好定位。

总结:

RN在android上确实不太完善,调试工具,错误提示,文档等都不是很友好。但去学习下还是挺酷的,而且在facebook不遗余力的推动,相信会越来越完善的。

React Native项目组织结构介绍的更多相关文章

  1. Expo大作战(三)--针对已经开发过react native项目开发人员有针对性的介绍了expo,expo的局限性,开发时项目选型注意点等

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  2. 【腾讯Bugly干货分享】React Native项目实战总结

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...

  3. React Native 项目运行在 Web 浏览器上面

    React Native 的出现,让前端工程师拥有了使用 JavaScript 编写原生 APP 的能力.相比之前的 Web app 来说,对于性能和用户体验提升了非常多. 但是 React Nati ...

  4. 使用Visual Studio Code和typescript 开发调试React Native项目

    关于React Native的详细介绍我就不叙述了,他是使用js构建原声app的开发框架.一次变异多平台运行,非常强大.但是个人不喜欢js的过于灵活(弱类型)的语法.强大的强类型语言Typescrip ...

  5. React Native 项目实战-Tamic

    layout: post title: React Native 项目实战 date: 2016-10-18 15:02:29 +0800 comments: true categories: Rea ...

  6. React Native 项目整合 CodePush 全然指南

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/y4x5M0nivSrJaY3X92c/article/details/81976844 作者 | 钱 ...

  7. 技术实践丨React Native 项目 Web 端同构

    摘要:尽管 React Native 已经进入开源的第 6 个年头,距离发布 1.0 版本依旧是遥遥无期."Learn once, write anywhere",完全不影响 Re ...

  8. react native项目启动需要做的操作

    一.启动: 1.查看端口(默认8081是否被占用) netstat -ano   可以查看所有的进程 2.netstat -ano | findstr "8081"  查看某个端口 ...

  9. React Native项目集成iOS原生模块

    今天学习一下怎么在React Native项目中集成iOS原生模块,道理和在iOS原生项目中集成React Native模块类似.他们的界面跳转靠的都是iOS原生的UINavigationContro ...

随机推荐

  1. tensorflow rnn 最简单实现代码

    tensorflow rnn 最简单实现代码 #!/usr/bin/env python # -*- coding: utf-8 -*- import tensorflow as tf from te ...

  2. 获取X天后的日期

    import java.util.Calendar; import java.util.Date; public class main { public static void main(String ...

  3. 小程序上拉下拉共存时不可使用scroll-view的解决方法

    使用 bindscrolltolower ,必须搭配使用的 scroll-view 会导致小程序 "enablePullDownRefresh": true 下拉不能使用. 解决方 ...

  4. iOS 选择排序

    简单选择排序的基本思想:(从小到大) 第1趟,在待排序记录r[1]~r[n]中选出最小的记录,将它与r[1]交换: 第2趟,在待排序记录r[2]~r[n]中选出最小的记录,将它与r[2]交换: 以此类 ...

  5. Docker容器如何互联

    容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式. 该系统会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息. 自定义容器命名 连接系统依据容器的名称来执 ...

  6. Python3 解释器

    Linux/Unix的系统上,Python解释器通常被安装在 /usr/local/bin/python3.4 这样的有效路径(目录)里. 我们可以将路径 /usr/local/bin 添加到您的Li ...

  7. Android简易实战教程--第三十八话《自定义通知NotifiCation》

    上一篇小案例,完成了一个普通的通知,点击通知启动了一个活动.但是那里的通知没有加入些"靓点",这一篇就给它加入自定义的布局,完成自定义的通知. 应用:比如QQ音乐为例,当点击音乐播 ...

  8. jdbc批量插入

    分享牛,分享牛原创.有这样一个需求,文本文件中的数据批量的插入mysql,怎么用jdbc方式批量插入呢? jdbc默认提供了批量插入的方法,可能用一次就忘记了,这里做笔记记录一下jdbc批量插入吧. ...

  9. Android图表库MPAndroidChart(九)——神神秘秘的散点图

    Android图表库MPAndroidChart(九)--神神秘秘的散点图 今天所的散点图可能用的人不多,但是也算是图表界的一股清流,我们来看下实际的效果 添加的数据有点少,但是足以表示散点图了,我们 ...

  10. Ubuntu Intel显卡驱动安装 (Ubuntu 14.04--Ubuntu 16.10 + Intel® Graphics Update Tool)

    最近使用在使用Ubuntu时,发现大部分情况下,不安装显卡驱动,使用默认驱动,都是没有问题的,但对于一些比较奇特配置的电脑,如下所示,如果使用默认驱动,会时常莫名其妙死机crash,尤其是在使用Ope ...