# React-Native记（一）

> 原文：https://pjhubs.com/2018/01/19/React-Native%E8%AE%B0%EF%BC%88%E4%B8%80%EF%BC%89/
>
> 作者：PJHubs · 发布于 2018-01-19 · 标签：跨平台、React-Native

期末考完了，RN的学习一直在进行着，这段时间初步的学习了RN的一些基本组件、触摸事件及相关的生命周期等，整体给我的感觉与之前的微信小程序开发流程非常相似，甚至某些地方如出一辙，不能说微信小程序抄了RN，反而微信小程序的开发体验上会给人一种“阉割版”RN的感觉（可能这么形容不太恰当），但是总的来说，RN对于前端同学上手开发端会有一个无比大的优势，这优势甚至超过了做端的同学上手RN。

以上就是这段时间继续学习RN中给我的一些直观感受，因为也还在持续的学习当中，目前所遇到的情况都是“挖，RN这么强的吗？”，“这都行？”，“这么快？”等balabala，为啥我会发出这种感叹呢？按照以往来说，虽然纯Native开发整体给人会比较流畅并且开发体验也较好，但是唯一的痛点就是一个产品需要两波端同学同时开发，人力成本瞬间就上去了，而引入RN，甚至只需要前端同学就能够直接上了。

我在此总结了一番这段时间学习RN所遇到的或者可能给各位同学在未来学习RN少踩坑的总结，

1. 使用RN进行跨平台开发，最重要的就是“所见即所得”的开发快感，只需要保存一下，即可在对应的调试设备或者模拟器上看到修改后的效果。开启这种“所见即所得”的功能，如果你是iPhone真机，摇一摇弹出sheet后选择“Enable Live Reload”，Android真机需要点击“菜单键”即可弹出进行选择，如果你是iPhone模拟器，cmd+d即可弹出，若你是Android模拟器，我找了半天，模拟器自带的界面上是没有菜单键的，据说好像是google并不推荐Android上有菜单键这种东西？cmd+m弹出Android模拟器菜单。

2. 并且我们还能够使用浏览器来进行调试，当我们选择了“Debug JS Remotely”，那么会自动调出我们的默认浏览器，如果你是选择了Chrome作为默认浏览器，此时，我们把对应模拟器上作为chrome的View，使用开发者工具尽情调试吧~

3. RN跟我以往的开发流程不太一样，RN是面向组件开发的。比如我单独把登录页面拎出来，作为一个组件，
  <div align="center">    
  <img src="http://7xszq8.com1.z0.glb.clouddn.com/RN_1.png" width = "100%" height = "100%" align=center />
  </div>
而想要使用QQLoginView这个组件的时候，我只需要在对应的页面js中，通过require引入这个组件，按照模仿H5标签的写法，即可引入。
  <div align="center">    
  <img src="http://7xszq8.com1.z0.glb.clouddn.com/RN_2.png" width = "70%" height = "70%" align=center />
  </div>
这种思想跟面向对象的开发思路非常类似，到目前为止给我的感受就是换了种说法，😓。

4. 我是从iOS开发转入RN学习中来的，在这段时间中让我感到比较困惑的，就是RN每个页面的生命周期，在iOS中我们根据方法名基本上就能够推断出每一个类生命周期的对应阶段，比如ViewDidLoad、ViewWillAppear等，但是在RN中，emmmm。
RN组件的生命周期大致上可以分为**实例化阶段**、**存在阶段**和**销毁阶段**，其中最常用的为实例化阶段，基本上我们常用的所有的组件都在此阶段进行构建和展示等。
此外，现目前RN支持ES5和ES6，但是部分浏览器不支持ES6（其实我没懂到底是哪些浏览器，这都快三年了）市面上找到的资料大部分还是ES5，少部分高频组件或者方法都有ES6的做法，给我自己的感觉ES5和ES6差别还是很大的，ES6中较为完整的给JS补充了面向对象的基本内容，比ES5看上去更加的舒服。如果大家对ES5和ES6的区别感兴趣，可以参考[这篇文章](http://bbs.reactnative.cn/topic/15/react-react-native-%E7%9A%84es5-es6%E5%86%99%E6%B3%95%E5%AF%B9%E7%85%A7%E8%A1%A8/2)。（今后均以ES6进行讲解）
这是每个组件的生命周期开始时最先进行的两个步骤，先把可变变量和不可变变量都给你先执行，
```js
// 不可变 变量定义
static defaultProps={
    name: '1222'
}

// 可变 变量定义
constructor() {
    super();
    this.state = {
        title: '4666',
    }
}
```
    如果我们要修改相关变量，可以这么做，
```js
  // renderPress是一个普通的JS方法
  renderPress(event) {
      this.setState({
          title: this.props.name,
      })
  }
```
    如果组件要被加载在视图上之前做调用或者做一些其它的事情，比如iOS中的ViewWillAppear，在RN中，需要在**componentWillMount**方法中进行。

    **render**方法是一个组件中必须有的方法，相当于init（虽然在iOS中可以不用显式重载init），其本质上是一个函数，并返回其它调用或者组件构成DOM。在render函数中，只可通过this.state和this.props来访问在之前函数中初始化的数据值。

    **componentDidMount**在调用了render方法后，组件加载成功并被成功渲染出来以后，所要执行的后续操作，一般会在这个方法中处理网络请求等加载数据的操作；这一点跟iOS区别较大，RN中的这个方法相当于规避掉了以往端开发时手动异步的过程，只需要在该方法中重新setData一遍即可刷新当前页面。

5. 以上就是RN实例化阶段的方法分析，存在期阶段的相关方法因为才刚开始学习一段时间，具体的方法细节并未涉及到，在此就先po出来，后续填坑。
**componentWillReceiveProps**指父元素对组件的props或state进行了修改
**shouldComponentUpdate**一般用于优化，可以返回false或true来控制是否进行渲染
**componentWillUpdate**组件刷新前调用，类似componentWillMount
**componentDidUpdate**更新后的hook

6. RN和微信小程序数据更新后，如果需要重新刷新页面按照之前的说法，直接就是this.setData即可，但这是怎么做到的呢？可以说这是RN的一大创新，将组件看成是一个状态机，开始会有一个初始状态，如果用户跟组件有互动导致状态变化，即可从而触发重新渲染UI。如果我们想要拿到当前页面中的某个组件，也就是DOM树下的某个节点，在RN中可以通过this.refs.'DOM节点名'去获取，但前提得是给这个组件设置了ref属性值。在RN中，各个组件并不是真实的DOM节点，而是存在于内存之中的一种数据结构，叫做虚拟DOM。只有当虚拟DOM插入文档以后，才会变成真实的 DOM。根据RN的设计，所有的DOM变动，都先在虚拟DOM上发生，然后再将实际发生变动的部分，反映在真实DOM上，这种算法叫做**DOM diff**，它可以极大提高网页的性能表现。具体的应用场景就是一个输入框，如果我们需要拿到用户的输入，就得通过DOM去拿到当前输入框，最后才能取到对应的输入值。

7. 在普通的web开发中，我们是能够直接在空的div中写东西的，但是在RN中是不允许直接在view标签中直接写东西的，我感觉应该是通过这种JSX的写法应该没法识别没有标签的内容吧。2333。并且如果RN中的View里什么都没有，那我们实际上在设备中是看不到这个View，你必须保证这个View中是有内容的。并且在一个单独的组件中，你必须要把一个View标签套在其它标签之外，在iOS中，你可以认为是self.view。

8. 这是RN的注释写法，{/**/}。每次写注释都觉得很烦emmm。。并且RN同样也是推荐使用flex进行布局，在flex中有主轴和侧轴之分，默认使用'column'也就是纵向布局，其余的主轴对齐方式有flex-start, flex-end,space-between, space-around。如果你的元素并未设置高度，那么它将占满整个距离它最近的View的高度，若未设置宽度，则将自动把宽度设置为最小适应数值。所以，我们在考虑布局的时候，一定要组织好主侧轴的布局方式，因为真的很容易乱😂。

9. RN中同样也有内外联样式表的说法，如果你要对一个组件进行内联样式表的设置，可以直接这么写'styl=&#123;&#123; backgroundColor:’red' &#125;&#125;。并且我们最好是从Xcode工程中打开模拟器，而不是通过命令行run-ios的方式去启动模拟器，因为工程调起的模拟器和命令行调起的并不是同一个，导致在Xcode工程中加入的资源，并没有命令行调起的模拟器中找到。

---
以上就是这段时间学习RN的一些要点，po一张当前学习效果图
  <div align="center">    
  <img src="http://7xszq8.com1.z0.glb.clouddn.com/WechatIMG319.jpeg" width = "100%" height = "100%" align=center />
  </div>
