React Native精解与实战(txt+pdf+epub+mobi电子书下载)


发布时间:2020-10-07 10:54:03

点击下载

作者:邱鹏源

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

React Native精解与实战

React Native精解与实战试读:

前言

从2015年React Native框架发布开始,我就关注React Native框架的发展,在得知React Native框架将同时支持iOS平台与Android平台的部署后,我们就开始着手将之前的项目从混合开发的方式慢慢转移到使用React Native框架开发的方式上来。当时国内的React Native方面的资料非常少,很多难题的解决都需要查阅大量的国外文档,正是在这个摸索的过程中,加深了对React Native框架的理解。

后来,我们的很多Web项目都在使用React框架,React正是React Native最底层的技术框架,同时也深深体会到只有理解底层架构,才能对于很多表象的难题快速定位并找到解决方案。

本书基于我多年写的技术博客以及使用React Native框架的实战经验,我认为底层的原理永远比一些组件的使用方法更重要,所以本书介绍了大量框架底层原理。通过阅读本书你会发现掌握框架后,组件和API的使用将变得非常简单,希望你在学习时能体会到这种触类旁通的感觉。本书主要内容

本书分为两大部分,第Ⅰ部分“入门”包括第1~9章,介绍React Native框架的基本原理与使用;第Ⅱ部分“进阶”包括第10~15章,介绍React Native框架的高阶开发与App部署相关知识。

第1章介绍React与React Native框架产生的背景与原理,以及开发优势。

第2章介绍Node.js框架,并实战演示了React Native开发环境的安装与配置。

第3章介绍React Native框架的构成、工作原理、组件间通信以及生命周期,包括代码实战演示。

第4章介绍React Native页面布局开发使用的CSS Flex,帮助读者掌握好React Native框架中元素布局的基本方法。

第5章介绍React Native框架下iOS平台与Android平台环境配置与代码调试的方法,并对React Native框架的调试工具以及借助Chrome进行远程调试的方法进行了实战讲解。

第6章介绍React Native框架中常用的组件,如View、TabBar、NavigatorIOS、Image、Text、TextInput、WebView、ScrollView等。同时介绍了iOS平台与Android平台的适配以及更适合的第三方组件。

第7章介绍React Native框架重点API的使用,包括提示框、App运行状态、异步存储、相机与相册、地理位置信息、设备网络信息等API,希望读者熟练掌握这些基础API,进而能举一反三。

第8章介绍React Native框架下的网络请求以及列表数据的绑定,这是开发App需要使用的技术重点。

第9章介绍React Native开发生态下一些常用的第三方组件,通过代码实战的方式进行讲解,并介绍了如何快速地找到自己的项目需要使用的第三方组件。

第10章结合iOS与Android平台深入讲解了React Native框架的底层运行原理,并分别介绍了两个平台的部署与测试方法。

第11章介绍React Native框架下iOS平台的混合开发方法,通过混合开发,你可以在React Native框架下访问任何iOS原生平台。

第12章介绍React Native框架下Android平台的混合开发方法,以及案例分析。

第13章详细讲解React Native框架下iOS平台与Android平台的消息推送原理,并介绍两个平台的消息推送实战。

第14章介绍项目最终打包前App的图标与启动图的设置,并介绍了如何通过第三方工具快速生成这些相关资源。

第15章介绍React Native性能调优的方法与技巧,以便在App上架前测试以及后期App遇到性能问题时可以快速定位到问题所在。

本书附录简单剖析了React Native的源码,希望能帮助你深入研究React Native框架的源码,以便能探究其底层本质。同时也分享了一些学习React Native框架的相关资源。本书的读者对象

·各类移动App开发人员,学习React Native框架可以使你开发一套React Native源码同时部署到iOS平台与Android平台。

·想进入移动App开发领域的初学者,React Native框架比Android和iOS两个原生平台的技术门槛低很多,只需掌握HTML、CSS、JavaScript相关知识点就可以动手开发跨平台的移动App。

·已经在使用React Native框架开发移动App的开发人员,书中讲解了React Native框架的底层原理,以及与iOS平台、Android平台的高阶混合开发部分,完全用代码进行讲解,学习起来更加直观。本书配套源代码

本书的配套源代码都可以在https://github.com/ParryQiu/ReactNative-Book-Demo下载。

后续如果遇到React Native框架的大升级,我同样会在此代码库中相应地更新实战演示的代码。致谢

首先感谢多年来共事过的同事们、领导们,多年来容忍我在一些技术问题上吹毛求疵,给了我很多好的建议和思路启发。还要感谢吴怡编辑,从约稿到审稿,都体现了她的认真态度和专业知识,她能一针见血地指出问题所在,促使我更加认真、专业地去编写此书。

在编写的过程中,虽然对于每一个知识点我都查阅了大量的相关文档,但是本书涉及海量的知识点,难免会有疏漏,恳请各位读者斧正。邱鹏源2018年4月第Ⅰ部分入门第1章React与React Native简介

这一章我们将对React与React Native的基本概念进行介绍。首先,详细介绍React产生的背景及React的框架,然后简单介绍React的底层实现原理,最后介绍React Native的基本概念。

你将对React与React Native框架的发展、框架之间的关系有一个基本的了解,具体的技术细节在后续的章节将有更加详细的讲解与实战解读。1.1 React简介

React框架最早孵化于Facebook内部,Jordan Walke是框架的创始人。React作为内部使用的框架,在2011年的时候用于Facebook的新闻流(newsfeed),并于2012年用在了Instagram项目上。在2013年5月美国的JSConf大会上,Facebook宣布React框架项目开源。

图1-1为GitHub上React的开源项目截图,地址为:https://github.com/facebook/react/。

React框架产生的缘由是在当时的技术背景下,前端MVC(Model-View-Controller)框架性能不能满足Facebook项目的性能需求以及扩展需求,所以Jordan Walke索性就自己着手开始写React框架,这种精神值得学习。

在当时Facebook内部极其复杂的项目中,面临的一个问题是,在MVC架构的项目中当Model和View有数据流动时,可能会出现双向的数据流动,那么项目的调试以及维护将变得异常复杂。图1-1 GitHub上的React项目

React官方也说自己不是一个MVC框架(https://reactjs.org/blog/2013/06/05/why-react.html),或者说React只专注于MVC框架设计模式中的View层面的实现。

为了大大减少传统前端直接操作DOM的昂贵花费,React使用Virtual DOM(虚拟DOM)进行DOM的更新。

图1-2为React框架的基本结构,清晰明了地描述出了React底层与前端浏览器的沟通机制。

React的组件是用户界面的最小元素,与外界的所有交互都通过state和props进行传递。通过这样的组件封装设计,使用声明式的编程方式,使得React的逻辑足够简化,并可以通过模块化开发逐步构建出项目的整体UI。

React框架中还有一个重要的概念是单向数据流,所有的数据流从父节点传递到子节点。假设父节点数据通过props传递到子节点,如果相对父节点(或者说相对顶层)传递的props值改变了,那么其所有的子节点(默认在没有使用shouldComponentUpdate进行优化的情况下)都会进行重新渲染,这样的设计使得组件足够扁平并且也便于维护。图1-2 React框架结构

以下的示例代码演示了React框架基本组件定义以及单向数据流的传递。

完整代码在本书配套源码的01-01-02文件夹。

我们在index.js文件中定义React项目的入口,render函数中使用了子组件BodyIndex,并通过props传递了两个参数,id和name,用于从父组件向子组件传递参数,这也是React框架中数据流的传递方式: 1. /** 2. * 章节: 01-01-02 3. * index.js 定义了 React 项目的入口 4. * FilePath: /01-01-02/index.js 5. * @Parry 6. */ 7. 8. var React = require('react'); 9. var ReactDOM = require('react-dom'); 10. import BodyIndex from './components/bodyindex'; 11. class Index extends React.Component { 12.13. //生命周期函数 componentWillMount,组件即将加载 14. componentWillMount(){15. console.log("Index - componentWillMount");16. }17. 18. //生命周期函数 componentDidMount,组件加载完毕19. componentDidMount(){ 20. console.log("Index - componentDidMount");21. }22. 23. //页面表现组件渲染24. render() {25. return (26.

27. 28.
29. );30. }31. }32. 33. ReactDOM.render(, document.getElementById('example'));

在子组件BodyIndex中定义了state值,并通过setTimeout函数在页面加载5秒后进行state值的修改。页面表现层代码演示了如何读取自身的state值以及读取父组件传递过来的props值: 1. /** 2. * 章节: 01-01-02 3. * bodyindex.js 定义了一个名为 BodyIndex 的子组件 4. * FilePath: /01-01-02/bodyindex.js 5. * @Parry 6. */ 7. 8. import React from 'react'; 9. export default class BodyIndex extends React.Component { 10. constructor() { 11. super(); 12. this.state = { 13. username: "Parry" 14. }; 15. }16. 17. render() { 18. setTimeout(() => { 19. //5秒后更改一下 state 20. this.setState({username: "React"}); 21. }, 5000); 22. 23. return ( 24.

25. 26.

子组件页面

27. 28.

当前组件自身的 state

29.

username: {this.state.username}

30. 31.

父组件传递过来的参数

32.

id: {this.props.id}

33.

name: {this.props.name}

34. 35.
36. ) 37. } 38. }

项目的package.json文件配置和使用的相关框架版本如下所示: 1. { 2. "name": "01-01-02", 3. "version": "1.0.0", 4. "description": "", 5. "main": "index.js", 6. "scripts": { 7. "test": "echo \"Error: no test specified\" && exit 1" 8. }, 9. "author": "", 10. "license": "ISC", 11. "dependencies": { 12. "babel-preset-es2015": "^6.14.0", 13. "babel-preset-react": "^6.11.1", 14. "babelify": "^7.3.0", 15. "react": "^15.3.2", 16. "react-dom": "^15.3.2", 17. "webpack": "^1.13.2", 18. "webpack-dev-server": "^1.16.1" 19. }20. }

在命令行执行webpack-dev-server命令后,浏览器中的运行结果如图1-3所示,并且在5秒后子组件的state定义的username值由Parry变成了React。具体的配置方法及其意义将在后续章节讲解。

你可以直接在本地编写代码运行测试或直接下载本书配套源码运行,运行后,注意此state页面值更新的部分,整个页面没有进行任何的重新刷新加载,而只是进行了局部的更新,其原理详见下一节。图1-3 代码在浏览器中的执行结果

React框架底层的核心为Virtual DOM,也就是虚拟DOM。本节将介绍它的底层特性,只有理解了React框架底层的本质,才能更好地帮助你理解React框架的前端表现,并为后续章节讨论React Native框架的性能优化进行一定的知识储备。

传统的HTML页面需要更新页面元素,或者说需要更新页面时,都是将整个页面重新加载实现重绘,执行这样的操作不管是从服务器代价还是从用户体验上来说,“代价”都是非常昂贵的。后来,有了AJAX(Asynchronous JavaScript And XML)这样的局部更新技术,实现了页面局部组件的异步更新,不过AJAX在代码的编写、维护、性能以及更新粒度的控制上还是不太完美。

文档对象模型(Document Object Model,DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口。在HTML网页上,将构成页面(或文档)的对象元素组织在一个树形结构中,用来表示文档中对象的标准模型就称为DOM。

React在框架底层设计了一个虚拟DOM,此虚拟DOM与页面上的真实DOM相互映射,当业务逻辑修改了React组件中的state部分,如上例中,子组件的state值,username由Parry修改成了React,React框架底层的diff算法会通过比较虚拟DOM与真实DOM的差异,找出哪些部分被修改了最终只更新真实DOM与虚拟DOM差异的部分。此计算过程是在内存中进行的,所以React在前端中的高性能表现正是来自于其底层的优良设计。

图1-4展示了React中的虚拟DOM与页面真实DOM之间的关系,其间的差异通过React框架底层的diff算法获取。图1-4 React虚拟DOM与页面真实DOM

要更加深入地了解React在源码级别的实现原理,可以参考我博客里从React的源码角度对其底层批量更新state策略的分析文章:

·深入理解React JS中的setState

http://blog.parryqiu.com/2017/12/19/react_set_state_asynchronously/

·从源码的角度再看React JS中的setState

http://blog.parryqiu.com/2017/12/29/react-state-in-sourcecode/

·从源码的角度看React JS中批量更新State的策略(上)

http://blog.parryqiu.com/2018/01/04/2018-01-04/

·从源码的角度看React JS中批量更新State的策略(下)

http://blog.parryqiu.com/2018/01/08/2018-01-08/

通过以上对React框架的简介、代码演示以及底层原理的剖析得知,React最大的优势在于更新页面DOM时,对比于之前的前端更新方案,效率会大大提高。其实React并不会在state更改的第一时间就去执行diff算法并立即更新页面DOM,而是将多次操作汇聚成一次批量操作,这样再次大大提升了页面更新重绘的效率。

使用React框架开发,我们不会通过JavaScript代码直接操作前端真实DOM,而是完全通过state以及props的变更引起页面DOM的变更,相对于jQuery等框架那样进行大量的DOM查找与操作要简单、高效得多。

React框架在开源生态下,已经有大量的相关开源框架与组件可供使用,非常适合项目的快速开发。1.2 React Native简介

Facebook曾致力于使用HTML 5进行移动端的开发,最终发现与原生的App相比,体验上还是有非常大的差距,并且这种差距越来越大,特别是在性能方面。最终,Facebook放弃了HTML 5的技术路线,于2015年3月正式发布了React Native框架,此框架专注于移动端App的开发。

在最初发布的版本中,React Native框架只用于开发iOS平台的App,2015年9月,Facebook发布了支持Android平台的React Native框架。至此,React Native框架真正实现了跨平台的移动App开发,此举简直就是移动App开发人员的福音。

图1-5为GitHub上React Native的开源项目,地址为https://github.com/facebook/react-native/。图1-5 GitHub上React Native开源项目

React Native框架在React框架的基础上,底层通过对iOS平台与Android平台原生代码的封装与调用,结合前台的JavaScript代码,我们就可以编写出调用iOS平台与Android平台原生代码的App,这样编写的App的性能远远优于使用HTML 5开发的App性能,因为HTML 5开发的App只是在HTML 5外部包裹上一个程序外壳后在移动平台上运行,在性能与功能上都不能达到React Native框架的水准。

React Native框架提供了原生组件与底层API供开发者使用,这些自带的组件与API足以满足移动端App的开发需求,后续章节会详细讲解这些组件与API的概念与使用实战演示。

React Native框架还提供了与iOS平台、Android平台混合开发的接口,让开发者可以在React Native中调用iOS平台与Android平台中任意的原生API与代码,让可以在原生平台实现的任何功能都可以在React Native框架中得以实现。

在使用React Native框架开发移动平台App的过程中,我们可以直接使用CSS进行页面元素的布局,这之前是iOS与Android原生移动平台开发者简直不可想象的事情。

开发人员在具备了React框架基础知识后,可以更加快速地进行React Native框架的学习与开发。图1-6为React Native官网截图,代码展示了我们只需要使用类似HTML 5(JSX)的代码就可以进行跨平台的移动App开发。图1-6 React Native演示代码

React Native有以下优势:

·底层采用React框架,减少了我们学习与开发的成本,React Native框架可以让你真正跨越移动开发的鸿沟,不需要分开学习iOS平台与Android平台的特定语法、页面布局以及各平台的特别处理技巧,使用一套React Native代码的部署就可以覆盖多个移动平台。

·React Native性能优化很好,完全可以避开之前使用HTML 5开发移动App的性能障碍。

·React Native框架的JavaScript Core底层,可以让App轻松实现更新操作,基本上更新一下JavaScript文件,整个App就完成了更新,非常适合用来开发App的热更新。

·React Native框架同时也使得App的开发调试变得异常简单,不需要像之前在多个平台、多个语言、多个工具之间跳来跳去,React Native开发的App在模拟器或真机中,只需要像刷新浏览器一样就可以即时查看到代码修改后的效果,并且还可以在Chrome浏览器中查看控制台输出、加断点、单步调试等,整个过程完全就是JavaScript开发调试的体验,非常畅快。

图1-7为使用React Native框架开发时,在iOS系统下的开发调试选项截图,功能非常强大、使用非常方便。Android平台提供了同样的调试选项。图1-7 React Native开发调试选项1.3 React Native前置知识点

在正式学习React Native框架前,我们梳理一下需要具备的基本知识,因为React Native毕竟是在多平台的移动App开发,涉及知识点比较多,而且底层的React框架有别于目前既有的一些前端框架知识。

·掌握HTML 5的基本知识;

·掌握JavaScript的基础知识,如果有React的基础知识学习起来会更加轻松;

·掌握CSS布局的基本知识,在React Native中会使用CSS直接进行页面元素的布局与样式控制;

·接触过移动端的开发更好,项目的后期会涉及两个平台的App打包、部署与上架,不过这些知识点后续章节都会讲解;

·Node.js以及npm包管理的知识,这部分后续章节同样会有详细的讲解。第2章Node.js简介与开发环境配置

本章将对开发过程中依赖的基础框架Node.js进行介绍,并深入讲解为什么使用此框架。同时我们将开始配置React Native的开发环境,并对代码编辑器Visual Studio Code以及相关高效开发插件做详细的介绍。2.1 Node.js与npm简介

本节对Node.js、npm进行了介绍,以及对需要使用到Node.js框架的原因进行了介绍。

1.Node.js简介

关于Node.js,官网(https://nodejs.org)给出的定义如下。

Node.js是一个基于Chrome V8引擎的JavaScript运行环境。Node.js使用了一个事件驱动、非阻塞式I/O的模型,使其轻量又高效。Node.js的包管理器npm,是全球最大的开源库生态系统之一。

虽然只有几句话,但是已经很清楚地描述了Node.js以及npm的概念。

Node.js本身并不是一个新的开发语言,也不是一个JavaScript框架,而是一个JavaScript运行时,底层为Google Chrome V8引擎,并在此基础上进行了封装,可用于创建快速、高效、可扩展的网络应用。Node.js采用事件驱动与非阻塞I/O模型,以使得Node.js轻量并高效。

图2-1为Node.js的架构图,可以看到底层使用C/C++编写。

·Chrome的V8引擎是用C++开发的,负责将JavaScript代码转换成机器码,所以引擎的整体执行效率非常高。Google Chrome浏览器的底层使用的就是V8引擎;

·线程池是完全使用C语言实现、全特性的异步I/O库libeio,用于执行异步的输入/输出、文件描述符、数据处理、sockets等;

·libev是在Node.js内部运行的event loop,最早用于类Linux系统。event loop是一个让多线程执行更加高效的程序结构;

·这些框架实现的语言不一样,有C,有C++,还有JavaScript,那么将这些代码整合在一起就是Node bindings要做的事情;

·最上层是使用Node.js开发时接触到的应用层,Node.js提供了一系列标准的JavaScript类库供开发者使用。图2-1 Node.js架构图

2.npm简介

npm是Node.js的包生态系统,是最大的开源生态系统。可以理解为基于Node.js框架,全世界的开发者提交了各种各样的功能类库到npm中,其他开发者在开发过程中需要使用的大部分功能都可以在npm中找到已存在的库,完全不需要自己“造轮子”。

截至2018年3月npm官网(https://www.npmjs.com/)上已有60多万个包,是一个非常大的宝库,你可以下载、使用、学习各种类库,当然,也可以贡献自己的类库到npm中供其他开发者使用。

可以在npm中直接搜索你在开发过程中需要使用到的任何功能库,假设你需要一些关于cookie处理的JavaScript类库,图2-2就是在npm中搜索cookie相关类库的结果。使用npm库是你使用React Native开发App肯定会接触到的一个过程。图2-2 npm中搜索类库

3.React Native与Node.js的关系

Node.js提供了很多的系统级的如文件操作、网络编程等特性,并且是事件驱动、异步编程的。React构建于Node.js之上,其实本质上React也是npm包中的一个,React Native也是npm包之一,只不过是功能非常强大的包而已。所以整个的框架都构建于Node.js之上,并且Node.js还提供了海量的类库,在这个完整的生态系统下开发,过程将变得更加高效,在后续的章节中将会慢慢体会到此生态系统的价值。2.2 React Native开发环境配置

本节我们将开始配置React Native的开发环境,包括Node.js的安装与React Native的安装,并介绍代码编辑器Visual Studio Code以及高效开发插件的安装,工欲善其事必先利其器,搭建一个完美的开发环境,学习起来才会更加顺畅。2.2.1 安装Node.js

Node.js提供了多个平台的安装包,掌握了Node.js,可以开发出很多跨平台的应用。

在图2-3的下载地址(https://nodejs.org/en/download/)中,显示了Node.js目前可以下载安装的平台。图2-3 Node.js下载页面

可以根据自己特定的开发环境,下载对应的版本安装即可。Node.js官方推荐下载LTS版本,LTS俗称长效版,框架整体的变更不频繁、稳定可靠,一般用于上线版本,当然学习环境的安装也推荐安装此版本。

如果需要安装其他的版本,在此下载页面的底部有Previous Releases链接,可查看到Node.js已发布的所有版本安装包。

下面以macOS系统为例,进行Node.js的安装。Windows等其他平台下载对应的安装包安装即可,整个过程没有需要特别配置的地方,只要注意Node.js的安装包分为32位和64位,下载你电脑对应的安装包即可,且需要安装最低版本为4.0以上的Node.js。

这里演示的是Node.js 6.11.3版本的安装,如图2-4所示,双击安装包进行安装,界面会有当前安装包包含的Node.js版本和npm版本的提示。图2-4 安装Node.js的版本提示

安装程序需要确认Node.js的License,点击同意即可。同时会提示占用的系统空间,继续下一步。如图2-5所示,安装程序会进行安装,安装完成后,会在界面中提示Node.js和npm最终安装的路径,需要检查系统的全局变量是否已包含了对应的目录,一般都是默认配置好的。图2-5 Node.js安装完成的提示信息

在Node.js安装完成后,可以通过命令行检查Node.js以及npm是否安装成功。打开macOS的终端或者Windows系统的命令行工具,输入命令node–v可以查看到当前安装成功的Node.js版本信息,输入npm–v可以查看到当前连带安装的npm版本信息。

运行结果如图2-6所示,至此说明Node.js框架已安装成功。图2-6 命令行查看Node.js和npm的版本信息2.2.2 安装React Native

在安装React Native框架之前,我们需要安装监控文件变更的组件watchman,便于后期React Native项目的打包更新时提高性能之用。

在命令行中输入命令brew install watchman即可安装,前提是确保系统中已安装好了Homebrew(https://brew.sh/)。

安装过程如图2-7所示,首次更新Homebrew的时间可能稍长,耐心等待片刻即可。

注意在Windows环境下不需要进行Homebrew和watchman的安装,跳过此安装步骤即可。图2-7 在macOS下安装watchman

接下来我们开始安装React Native,之前介绍npm时说过,React Native也是一个npm的包,那么这里就可以通过npm命令进行React Native框架的安装。

图2-8为React Native在npm包中的项目页面,地址为:https://www.npmjs.com/package/react-native。图2-8 npm中的React Native项目页面

在npm下安装一个包的命令格式为:npm install+包的名称,如果加上参数g,命令npm install–g+包的名称,就是全局安装,而不仅仅是在运行命令的当前目录中安装。

所以,我们通过npm命令执行安装React Native CLI的命令行工具即可,后续的React Native项目初始化都可以通过React Native CLI命令行工具执行。

安装命令为:npm install-g react-native-cli。

命令执行的结果如图2-9所示。

下面我们在本书配套源码的02-02-02文件夹中进行第一个React Native项目的初始化,执行命令:react-native init HelloReact。

命令执行过程如图2-10所示。图2-9 安装React Native CLI图2-10 初始化React Native项目

初始化完成后,最终生成的项目文件结构如图2-11所示。图2-11 React Native初始化项目结构

我们使用Xcode打开ios文件夹中的iOS项目以及使用Android Studio导入android文件夹中的Android项目。

iOS平台的执行结果如图2-12所示,可以看到,React Native构建的项目直接就适配好了iPhone X,其他的iOS设备适配当然也没有任何问题。图2-12 项目在iOS平台下运行

Android平台的执行结果如图2-13所示,同样,也可以完全适配。图2-13 项目在Android平台下运行

到目前为止还没有写过任何一行代码,生成的App却已经可以完美地适配iOS与Android两个平台,这正是React Native平台的魅力所在,后续的实战章节我们还将继续领略此框架的魅力。2.2.3 代码编辑器以及推荐插件

一个好的代码编辑器会让你的开发效率成倍地提升,这里从性能、界面、插件生态系统以及编辑器的更新迭代情况综合考虑,推荐大家使用微软推出的、免费的Visual Studio Code,的确非常好用,可以说它是目前前端开发的首选编辑器。图2-14是Visual Studio Code编辑器的主界面,编辑器的左侧五个按钮依次为:项目文件浏览器、代码搜索、git管理、调试工具、插件安装,右侧为代码编辑界面,最下面的状态栏包含了如git信息、代码定位、代码中的错误与警告、文件编码、代码格式等相关信息。图2-14 Visual Studio Code编辑器

Visual Studio Code还有一个很大的优势就是有很多提升开发效率的插件,这里推荐几个开发React Native项目必备的插件,这些插件会大大提高你的开发效率。你只需要直接在编辑器的插件选项中搜索名称即可安装。

Visual Studio Code编辑器的插件安装界面如图2-15所示,在左侧的菜单按钮中选择插件,然后你可以在图中标示的搜索框中搜索需要安装插件支持的语言或直接输入插件名称,在搜索结果列表中选择对应的插件点击安装按钮即可。图2-15 编辑器插件安装

1.React Native Tools

此插件提供React Native的开发环境,可以直接在编辑器中使用React Native CLI的命令,并可以对React Native框架提供的函数、参数、API等进行智能提示,非常方便。

插件地址:https://marketplace.visualstudio.com/items?itemName=vsmobile.vscode-react-native/。

2.ES7 React/Redux/GraphQL/React-Native snippets

此插件在开发时提供React Native中会使用到的ES语法,可以快速生成输入。

如导入模块命令import moduleName from'module'可以直接使用imp输入、导出模块命令export default moduleName只需要输入exp即可。

熟悉这些命令之后,可以省去很多书写特定代码的时间。

插件地址:https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets/。

3.react-beautify

此插件用于快速格式化React Native开发过程中的JavaScript、JSX等代码,免去很多手动整理代码格式的过程,保持规范、整洁、易读的代码格式,是一个优秀软件工程师的必备素养。

插件地址:https://marketplace.visualstudio.com/items?itemName=taichi.react-beautify/。第3章React Native工作原理与生命周期

本章将深入讲解React Native的底层原理,万丈高楼平地起,深入理解React Native底层的实现,有助于在开发中遇到难题时找到解决问题的思路。

本章介绍React Native的框架构成、工作原理、组件间通信,以及React Native中的生命周期。

如果需要直接进入React Native的开发与实战,可以从第4章开始学习。3.1 React Native框架及工作原理

React Native框架内部提供了很多的内置组件,如图3-1所示。包括基本组件,如View、Text等,用于一些功能布局的Button、Picker等,iOS平台与Android平台的特定组件、API等。同时也提供了接口便于与原生平台进行交互。后续的章节我们会介绍与原生平台的混合实战开发。

在介绍React框架的章节,我们理解了如何将代码渲染至虚拟DOM并更新到真实DOM的过程。在React Native框架中,渲染到iOS平台与Android平台的过程如图3-2所示。

在React框架中,JSX源码通过React框架最终渲染到了浏览器的真实DOM中,而在React Native框架中,JSX源码通过React Native框架编译后,通过对应平台的Bridge实现了与原生框架的通信。如果我们在程序中调用了React Native提供的API,那么React Native框架就通过Bridge调用原生框架中的方法。图3-1 React Native框架构成图3-2 React Native渲染

因为React Native的底层为React框架,所以,如果是UI层的变更,那么就映射为虚拟DOM后调用diff算法计算出变动后的JSON映射文件,最终由Native层将此JSON文件映射渲染到原生App的页面元素上,实现了在项目中只需控制state以及props的变更来引起iOS与Android平台的UI变更。

编写的React Native代码最终会被打包生成一个main.bundle.js文件供App加载,此文件可以存储在App设备本地,也可以存储于服务器上,以供App下载更新,后续章节讲解的热更新就会涉及main.bundle.js位置的设置问题。3.1.1 React Native与原生平台通信

React Native在与原生框架通信中,如图3-3所示,采用了JavaScriptCore作为JS VM,中间通过JSON文件与Bridge进行通信。若使用Chrome浏览器进行调试,那么所有的JavaScript代码都将运行在Chrome的V8引擎中,与原生代码通过WebSocket进行通信。图3-3 React Native与原生平台的通信3.1.2 组件间通信

React Native开发最基本的元素就是组件,React Native与React一样,也会涉及组件之间的通信,便于数据在组件之间传递,下面列出了几种常用的组件间通信方式。

1.父子组件的通信

如同之前介绍React组件间参数传递一样,在React Native中,可以通过props的形式实现父组件向子组件传递值。

在下例中,父组件通过调用子组件并赋值子组件的name为React,子组件通过this.props.name获取父组件传递过来的name的字符串值React。

完整代码在本书配套源码的03-04文件夹。 1. /** 2. * 章节: 03-04 3. * 父子组件通信,在父组件中调用子组件 4. * FilePath: /03-04/parent-2-child.js 5. * @Parry 6. */ 7. 8. 9. 10. /** 11. * 章节: 03-04 12. * 子组件实现,通过 props 获取父组件传递的值13. * FilePath: /03-04/parent-2-child.js 14. * @Parry 15. */ 16. 17. class ChildComponent extends Component { 18. render() { 19. return ( 20. Hello {this.props.name}!21. );22. }23. }

2.子父组件的通信

在开发过程中,还会有子组件向父组件通信传递值的需求,比如当子组件的某个值变更后,需要通知到父组件做相应的变更与响应,那么就需要子父组件之间的通信。

例如,在父组件的定义中,在调用子组件时,同样向子组件传递了一个参数,不过这个参数是一个函数,此函数用于接收后续子组件向父组件传递过来的数据,与之前父组件向子组件传递数据不太一样。

完整代码在本书配套源码的03-04文件夹。 1. /** 2. * 章节: 03-04 3. * 子父组件通信,父组件的实现 4. * FilePath: /03-04/child-2-parent.js 5. * @Parry 6. */ 7. import React, {Component} from 'react'; 8. import ChildComponent from './ChildComponent' 9. 10. class App extends Component { 11. constructor(props) { 12. super(props) 13. this.state = { 14. name: 'React' 15. } 16. } 17. 18. //传递到子组件的参数,不过参数是一个函数。 19. handleChangeName(nickName) { 20. this.setState({name: nickName}) 21. } 22. 23. render() { 24. return ( 25.

26.

父组件的 name:{this.state.name}

27. { 29. this.handleChangeName(val) 30. }}/> 31.
32. ); 33. } 34. } 35. 36. export default App;

下面为子组件的定义,子组件在页面中定义了一个按钮,点击此按钮调用自身的一个函数handleChange,修改了自身state中的值name为nickName定义的值Parry,那么此子组件的页面上的字符串将由之前的Hello React!变为Hello Parry!,同时使用了this.props.changeName,也就是父组件调用时传递过来的函数,向父组件传递了nickName的值Parry。

父组件在接收到子组件的调用后,调用了父组件自身的函数handleChange Name修改了自身的state中的name的值为Parry,也就是子组件传递过来的Parry,所以,父组件的页面上的值也同时由之前的React变更成了Parry。代码如下: 1. /** 2. * 章节: 03-04 3. * 子父组件通信,子组件的实现 4. * FilePath: /03-04/child-2-parent.js 5. * @Parry 6. */ 7. 8. import React, {Component} from 'react' 9. 10. export default class ChildComponent extends Component { 11. constructor(props) { 12. super(props) 13. 14. this.state = { 15. name: 'React' 16. } 17. } 18. 19. handleChange() { 20. const nickName = 'Parry'; 21. this.setState({name: nickName}) 22. //调用父组件传递过来的函数参数,传递值到父组件去。 23. this 24. .props 25. .changeName(nickName) 26. } 27. 28. render() { 29. const {name} = this.state; 30. return ( 31.

32.

Hello {name}!

33. 38.
39. ) 40. } 41. }

3.多级组件之间的通信

如果组件之间的父子层级非常多,需要进行组件之间的传递,这时候当然可以通过上面介绍的方法逐级传递,但这样的传递方法不是一个太好的方法。

因为组件之间通信冗长,嵌套逻辑太深,会导致用户体验不好,可以想象一下用户从最底层一层层操作返回到最顶层时的体验。

可以使用如context对象或global等方式进行多级组件间的通信,但是不推荐这种方式。最好不要让组件之间的层级关系太深。

4.无直接关系组件间通信

前面提到的都是有层级关系的组件间的通信方式,如果组件间没有层级关系的话,则可以通过如AsyncStorage或JSON文件等方式进行通信。

当然,还可以使用EventEmitter/EventTarget/EventDispatcher继承或实现接口的方式、Signals模式或Publish/Subscribe的广播形式,都可以达到无直接关系组件间的通信。

这些组件间的通信方式使得组件之间可以传递数据,后续的实战章节会有详细的代码实现,这里主要进行了理论的介绍。掌握这部分知识后才可以将App开发中的基本单位(也就是组件)串联起来。3.2 React Native中的生命周期

任何生命体都会经历从出生到消亡的过程,React Native框架中的组件同样具有这样的属性。在组件生命周期的每个阶段,React Native提供了多个生命周期函数,供开发者作为切入组件的钩子(hook),这样在对应的时间点程序就可以做对应的逻辑处理,从而实现相应的功能。

在React Native程序启动时,内部的虚拟DOM开始建立,生命周期就是建立在此虚拟DOM的整个生命周期之中,从虚拟DOM的初始化到虚拟DOM的卸载,React Native为组件的不同状态建立了不同的生命周期。

在图3-4中,可以看到在React Native虚拟DOM的几个大的阶段中,都存在对应的生命周期函数。下面就分阶段介绍。图3-4 React Native中的生命周期

1.初始化阶段

此阶段设定组件props和state的默认值,可通过如下代码赋值:1. static defaultProps = { 2. autoPlay: false, 3. maxLoop: 10, 4. };

2.加载阶段

此阶段为组件开始实例化的阶段,比如当该组件被其他组件调用的时候。主要包含以下三个函数:

·componentWillMount:组件将要开始加载,若需要在组件开始加载前添加一些业务逻辑,那么就可以在此函数中添加。

·render:组件开始根据props和state生成页面的DOM,并最终返回此DOM。在此函数中不可以修改props和state的值,只可以读取,并且返回的DOM只能有一个顶层元素,比如说只能由一个div包裹所有的元素返回。

·componentDidMount:组件已加载完毕,在render函数之后立即执行此函数。可以在这里进行网络请求,因为组件UI渲染好之后再进行网络请求,一般不会造成UI的错乱问题。在此生命周期函数中修改了state的值后,UI会立即进行重新渲染,所以这是一个通过加载网络数据更新UI的好时机。

3.更新阶段

当用户操作或者父组件有更新并且组件由于props或state的变更导致组件需要重新渲染时,会经历此阶段。而在更新渲染的几个重要时机,React Native提供了如下的生命周期函数供开发者执行对应的逻辑操作:

·componentWillReceiveProps:当接收到更新的props值时,会执行此函数,此时可以将接收到的props值赋值给state。

·shouldComponentUpdate:此函数用于判断新的props和state的变更需不需要引起组件的UI更新,默认是都会引起更新的,但是React Native提供了此函数供开发者自主决定是否需要更新。如果此函数返回True,那么组件将进行更新,如果返回False,那么组件就不更新。此函数在优化App性能时非常重要,因为可以通过此函数拦截掉很多不必要的组件UI更新。

·componentWillUpdate:如果以上函数shouldComponentUpdate返回了True,那么此函数将继续执行,表示组件即将进行更新操作。在更新操作前,还有时机进行相关的逻辑处理。但是从逻辑上你也应该明白,这里不可以再修改state的值,而只需做一些更新前的其他准备工作。

·componentDidUpdate:组件更新完毕之后执行的函数。此函数有两个参数prevProps和prevState,分别为更新前的props与state。这里可以进行新旧值的比较,如果发现值有变化则可以进行一些网络请求、加载数据等操作。

4.卸载阶段

·componentWillUnmount:此函数在组件被卸载和注销前执行,这里可以进行一些所谓的扫尾工作,如关闭之前的网络请求、清空一些不必要的存储、循环执行的定时器的清除等。

至此,React Native一个组件的完整生命周期执行完毕,你可以通过下面的代码体会React Native每个阶段的执行过程。实际开发时只需要根据项目需求在对应的生命周期函数中添加上自己的业务逻辑即可。 1. /** 2. * 章节: 03-06 3. * React Native 中的生命周期 4. * FilePath: /03-06/lifecycle.js 5. * @Parry 6. */ 7. 8. import React, { Component } from 'react'; 9. import { AppRegistry,View,Text } from 'react-native'; 10.

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载