React Native学习一:初识React Native

来源:互联网 发布:网络之大神我只是路过 编辑:程序博客网 时间:2024/05/16 04:40

React Native概述

什么是React Native

React Native是Facebook在React.js Config 2015 大会上推出的一个用于开发Android和iOS App的一个框架。主要编程语言是JavaScript,UI使用JSX(一种语法类似于XML的UI描述语言)。

React Native与React.js区别

那么React Native与React.js有什么区别呢?
任何一种跨平台框架都有两个部分:UI和逻辑。对于这两种技术来说,UI都使用的是JSX,而逻辑都是用的是JavaScript。
React Native与React.js的主要区别还是JSX,不管是React Native还是React.js,在UI上都是用了一种技术:虚拟DOM(Virtual DOM)。

那么什么是虚拟DOM呢?
其实JSX只是一种语法糖。DOM(Document Object Model 文档对象模型)是WEB前端描述网页的一种树形数据结构,WEB通过DOM管理Element,而DOM的效率是比较低的,为了提高DOM的效率,React.js提供了虚拟DOM,这项技术的工作是完全在内存中实现的,而且是增量修改DOM树,所以效率非常高。

对于WEB来说,在实际渲染时,仍然需要DOM,所以最终渲染时,虚拟DOM仍然要转换成实际DOM。而对于Android或者iOS,就没有DOM的概念,UI完全是本地控件实现的,如Android中的TextView和EditText等。所以React Native就应运而生,如果说React.js是在运行时将虚拟DOM映射成实际DOM,那么React Native就是在运行时将虚拟DOM映射成Android或者iOS的本地控件。
从这一点可以看出,React.js用于WEB开发,而React Native用于开发Android和iOS App,它们都将UI抽象成虚拟DOM,只是实际运行时,前者将虚拟DOM映射成了DOM,后者将虚拟DOM映射成Android或iOS的本地控件。

为什么需要 React Native?

What we really want is the user experience of the native mobile platforms, combined with the developer experience we have when building with React on the web.
摘自2015.3.26 React Native的发布稿,加粗的关键字传达了React Native的设计理念:既拥有Native的用户体验、又保留React的开发效率。这个理念似乎迎合了业界普遍存在的痛点。

React Native项目成员Tom Occhino发表的React Native: Bringing modern web techniques to mobile,详细描述了React Native的设计理念。Occhino认为尽管Native开发成本更高,但现阶段Native仍然是必须的,因为Web的用户体验仍无法超越Native:

  • Native的原生控件有更好的体验;
  • Native有更好的手势识别;
  • Native有更合适的线程模型,尽管Web Worker可以解决一部分问题,但如图像解码、文本渲染仍无法多线程渲染,这影响了Web的流畅性。

Occhino没提到的还有Native能实现更丰富细腻的动画效果,归根结底是现阶段Native具有更好的人机交互体验。笔者认为这些例子是有说服力的,也是React Native出现的直接原因。

“Learn once, write anywhere”同样出自Occhino的文章。因为不同Native平台上的用户体验是不同的,React Native不强求一份原生代码支持多个平台,所以不提“Write once, run anywhere”(Java),提出了“Learn once, write anywhere”。

这里写图片描述

这张图是笔者根据理解画的一张示意图,自下而上依次是:

  1. React:不同平台上编写基于React的代码,“Learn once, write anywhere”。
  2. Virtual DOM:相对Browser环境下的DOM而言,Virtual DOM是DOM在内存中的一种轻量级表达方式(原话是lightweight representation of the document),可以通过不同的渲染引擎生成不同平台下的UI,JS和Native之间通过Bridge通信。
  3. Web/iOS/Android:上层与用户交互的UI界面。

React Native的优势

上面讲到React Native的设计理念:既拥有Native的用户体验、又保留React的开发效率,是如何实现的呢?

由于React Native的UI仍然使用Android或iOS的本地控件,所以在UI渲染上已经非常接近Native App了。尽管业务逻辑代码使用JavaScript,但由于JavaScript是即时编译的,也就是第一次使用时会将JavaScript代码编译成二进制文件,所以JavaScript得运行效率比较高。因此,React Native的运行效率要比基于HTML5、CSS等技术的PhoneGap、AppCan高很多(国内外比较流行的Hybrid混合开发方式,原理是依赖Android或iOS的webview浏览器显示HTML5,是纯的WEB程序在移动端的运行),因为这些技术直接使用HTML5进行渲染,而HTML5会大量使用DOM技术,DOM在PC端的WEB应用中也不算快,在移动端就更慢了。

React Native一旦虚拟DOM映射本地控件完成,理论上来说,使用React Native所编写的App的运行效率和我们使用本地语言(Android的Java,iOS的OC或Swift)开发的App达到一致。

总结:
基于React Native的App在运行效率上接近于Native App,而且还具有混合开发模式的两个优点:

  • 热更新(无需重新编译上传App即可更新,而且还不用通过App Store审核)
  • 跨平台(降低了学习成本,使用同样的技术开发Android和iOS应用)

React Native特点

虚拟DOM

提到React最先想到的就是虚拟DOM。因为这个想法实现是太好了。简而言之就是,React中UI界面是一棵DOM树,对应的我们创建一个全局唯一的数据模型,每次数据模型有任何变化,都将整个数据模型应用到UI DOM树上,由React来负责去更新需要更新的界面部分。
传统的DOM比较需要一个节点一个节点比,时间复杂度是O(N3),React 通过分层求异的策略,对 tree diff 进行算法优化,简单说,这种虚拟DOM算法是同级的进行比较,并不进行跨层级比较,所以比较一次只需要O(N)的时间,效率非常高。当然这种情况下如果你对组件进行跨层级的移动,虚拟DOM会认为是删除了一个组件而新建了一个组件,会影响效率,所以开发中一般不进行跨层次的移动组件。
此外,React对同层级的比较中通过设置唯一 key的策略来优化了比较策略,大大的提高了效率,具体的看下这篇博客—不可思议的react diff,写得很清楚。这里就不再赘述。

JSX定义界面

JSX是React的核心组成部分,它使用XML标记的方式去直接声明界面,将HTML直接嵌入到JavaScript代码中。看下示例代码:

var React = require(‘React’);var message =  <div class=“hello”>    <span>Hello World</span>  </div>;React.renderComponent(message, document.body);

很奇怪的写法。但是确很直观,开发起来也很快。不需要过多考虑模板的概念,只需要考虑如何用代码构建整个界面。

单向数据流

React本身只是View层,对于事件传输层FB建议使用Flux这种单向传输架构。Flux 是一种架构思想,它分为View(视图层)、Action(动作)、Dispatcher(派发器)、Store(数据层)四层。数据流的流向参考下图:
这里写图片描述

首先用户访问 View,并通过View 发出用户的 Action。Dispatcher 接到Action后就要求 Store 进行相应的更新。store更新后会发一个事件到View上,最后View更新页面。简单的理解可以认为它是一种全局的消息发布订阅模型。Action可以来自于用户的某个界面操作,比如点击等;也可以来自服务器端的网络返回。当数据模型发生变化时,就触发刷新整个界面。
看下这篇文章—Flux架构入门。在RN中用的比较多的Flux框架是Redux,可以看这个链接进行学习—Redux自述。

独特的数据模型

React的所有数据都是只读的,如果需要修改它,那么你只能产生一份包含新的修改的数据。这样做是为了让代码更加的安全和易于维护。React将用户界面看做简单的状态机器。当组件处于某个状态时,那么就输出这个状态对应的界面。在React中,只要简单的去更新某个组件的状态,React就公以最高效的方式去比较两个界面并更新DOM树。

React-Native生命周期

与Activity类似,RN也有自己的生命周期。先看下我在网上找的一张生命周期图,很完整:
这里写图片描述

下面分点讲下各种方法:

  • getDefaultProps:在组件创建之前,会先调用 getDefaultProps(),这是全局调用一次。在组件被创建前加载。
  • getInitialState(),来初始化组件的状态。
  • componentWillMount:准备开始加载组件。在整个生命周期中只被调用一次,可以在这里做一些业务初始化操作,也可以设置组件状态。
  • componentDidMount:在组件第一次绘制之后调用,这个函数调用的时候,其虚拟DOM已经构建完成,你可以在这个函数开始获取其中的元素或者子组件了。需要注意的是,RN 框架是先调用子组件的componentDidMount(),然后调用父组件的函数。从这个函数开始,就可以和 JS 其他框架交互了,例如设置计时setTimeout 或发起网络请求。这个函数之后,就进入了稳定运行状态,等待事件触发。
  • componentWillReceiveProps:如果组件收到新的props,就会调用componentWillReceiveProps(),在这个回调函数里面,你可以根据属性的变化,通过调用 this.setState()来更新你的组件状态,这里调用并不会触发额外的 render() 调用。
  • shouldComponentUpdate:当组件接收到新的属性和状态改变的话,都会触发调用shouldComponentUpdate(…),这个函数的返回值决定是否需要更新组件,如果true表示需要更新,继续走后面的更新流程。否者,则不更新,直接进入等待状态。
  • componentWillUpdate:如果组件状态或者属性改变,并且上面的 shouldComponentUpdate(…) 返回为true,就会开始准更新组件,并调用componentWillUpdate(),在这个回调中,可以做一些在更新界面之前要做的事情。需要特别注意的是,在这个函数里面,你就不能使用this.setState来修改状态。紧接着这个函数,就会调用 render() 来更新界面了
  • componentDidUpdate:调用了 render() 更新完成界面之后,会调用 componentDidUpdate()来得到通知。
  • componentWillUnmount当组件要被从界面上移除的时候,就会调用componentWillUnmount()。在这个函数中,可以做一些组件相关的清理工作,例如取消计时器、网络请求等。
1 0
原创粉丝点击