代码组织:

目录结构:

.
├── components    //组成应用的各个组件
│   ├── Routers.android.js     //每个组件若实现不一样,分为android的实现和ios的实现。
│   ├── Routers.ios.js
│   ├── common     //公共组件
│   ├── issues        //议题页面
│   ├── navigation  //导航组件,android用侧边栏,ios准备用tab
│   └── project      //项目页面
└── network    //网络服务
    └── 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方法。

    • 很多地方的按钮都是返回上一级。
      <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>
    • 其他情况:
      参考这篇文章,不过目前我还没用到这种毫无关系的事件触发,所以尚未研究。

调试

  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的语法经常搞错,跟一般的模板语言不太一样。比如:

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项目组织结构介绍的更多相关文章

  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. net use命令详解

    net use命令详解 1)建立空连接: net use \\IP\ipc$ "" /user:"" (一定要注意:这一行命令中包含了3个空格) 2)建立非空连 ...

  2. Mysql优化--Show Profile

    Mysql 系列文章主页 =============== 是Mysql提供可以用来分析当前会话中语句执行的资源消耗情况.可以用于Sql的调优的测量.默认情况下处于关闭状态,并保存最近 15 次的运行结 ...

  3. Tomcat出现validateJarFile-jar not loaded问题

    tomcat启动时问题: validateJarFile(...\WEB-INF\lib\servlet-api.jar)-jar not loaded. See Servlet Spec 2.3, ...

  4. Echarts 中国地图各个省市自治区自定义颜色

    前言 最近接了一个外包的项目,其中有个需求是这样的, 需要展示一个中国的统计地图,要求每个省市区都是不一样的颜色,必须特别区分开.以及隐藏南海部分. 看了Echats相关文档,发现有类似的demo,但 ...

  5. jquery常用函数

    .text() //获得或更改元素文本: .html() //获得或更改元素标签: .val() //获得或更改input值: .css() //获得或更改元素样式: .click() //点击触发事 ...

  6. Structured Streaming + Kafka 集成中遇到的问题

    官方指导:http://spark.apache.org/docs/2.2.0/structured-streaming-kafka-integration.html 1.版本问题  起初用的kafk ...

  7. 实体类双向映射进行Json序列化时出现无限循环的解决问题

    1.@JsonIgnoreProperties 指定的字段不会被序列化,如下则ExamPaper的directory字段不会被序列化 @OneToMany(mappedBy = "direc ...

  8. 防止SpringMVC拦截器拦截js等静态资源文件

    SpringMVC提供<mvc:resources>来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决: 方案一.拦截器中增加针对静 ...

  9. android 获取栈顶activty的方法总结(兼容API 5.0)

    声明:本文为Dujinyang CSDN原创投稿文章,未经许可,禁止任何形式的转载. 最近5.0\6.0\7.0 安卓系统都陆续上岗了,兼容性和代码更新是个很头疼的问题,这次我们来说下TASK的基础和 ...

  10. SpringBatch简介

    spring Batch是一个轻量级的.完善的批处理框架,旨在帮助企业建立健壮.高效的批处理应用.SpringBatch是Spring的一个子项目,使用Java语言并基于Spring框架为基础开发,使 ...