专栏首页向治洪React Native项目组织结构介绍

React Native项目组织结构介绍

代码组织:

目录结构:

.
├── 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不遗余力的推动,相信会越来越完善的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • React Native组件生命周期

    概述 所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解空间的生命周期,是开发中必须掌握的一个知识点。就像 Android 开发中组件 一样,Re...

    xiangzhihong
  • 微信小程序基本组件概述

    为了更好的理解微信小程序,本文90%文字描述来源于官网的介绍。官网原链接https://mp.weixin.qq.com/debug/wxadoc/dev/co...

    xiangzhihong
  • iOS 组件化之路由设计思路分析

    前言 随着用户的需求越来越多,对App的用户体验也变的要求越来越高。为了更好的应对各种需求,开发人员从软件工程的角度,将App架构由原来简单的MVC变成MVVM...

    xiangzhihong
  • 基于组件的.NET技术(5)

    实战: 创建一个VB.NET Windows应用程序:VBTestDynamicComponent。将前面介绍的两个类ComponentList和LoadCo...

    脑洞的蜂蜜
  • 《精通react/vue组件设计》之5分钟实现一个Tag(标签)组件和Empty(空状态)组件

    本文是笔者写组件设计的第五篇文章,之所以会写组件设计相关的文章,是因为作为一名前端优秀的前端工程师,面对各种繁琐而重复的工作,我们不应该按部就班的去"辛勤劳动"...

    徐小夕
  • React高级特性解析

    使用API React.createContext  返回的是组件对象 可以利用结构的方式

    憧憬博客
  • React学习(最终篇)—— 高阶应用:高阶组件(HOCs)

    高阶组件(higher-order components:以下简称HOC或HOC组件)是一个React组件复用的高级技巧。HOCs本身并不是React的API接...

    随风溜达的向日葵
  • 构建Vue.js组件的10个技巧

    Vue.js提供了两种加载组件的方法:一种在Vue实例全局,另一种在组件级别。两种方法都有其自身的优点。

    前端知否
  • VUE组件传值案例讲解

    好吧我承认我疏忽了,我一直以为我的博客是将vue的一些常见操作全部写完了的,但是直到我写组件的时候突然想起来看一下自己写的博客是不是有问题的才发现,组件之间的传...

    何处锦绣不灰堆

扫码关注云+社区

领取腾讯云代金券