[关闭]
@hopefrontEnd 2018-12-05T07:23:42.000000Z 字数 10042 阅读 1495

React-Native 快速入门指南

ReactNative

使用React Native开发移动工程目前来说是十分高效的,但入门比较可能有点棘手, 本文综合笔者搭建、开发过程中的要点,难点,撰写了此篇入门指南帮助大家学习上手。 本文基本上上囊括了YDD-ReactNative开发过程中关键部分点,对陌生点给与文档指引及查看。

1. 环境

设置React Native开发环境有两种常用方法create-react-native-app and react-native-cli

1.1 create-react-native-app

React社区维护的一个命令行工具(Star数最高)。此工具会生成一个二维码,您可以扫描该代码以在您的设备上启动该应用。更新代码时,更改将自动反映在您的设备上。为了在您的设备上预览应用程序,系统会提示您下载应用程序,这是一个React Native应用程序预览客户端。
create-react-native-app Expo
Expo Expo类似于一个通用的SDK,提供了比较完善的UI组件和API功能, 安装时需要翻墙。
优点: 提供API较多, 开发调试环境方便。
缺点:最新的SDK只支持安卓5.0级以上,IOS10及以上,版本更新频繁。

Tips: 缺点此方式不适用于混合项目,适合纯ReactNative项目

1.2 react-native-cli

类似Vue-cli 可以用此创建一个自定义的模版程序
一个空白的RN项目

  1. react-native init AwesomeProject

1.3 调试及开发

更多参见React-Native开发环境简介

2. Javascript

2.1 Babel

Babel是用于预处理JavaScript的主要工具。Babel是一个高度可配置的编译器,允许您使用实验性功能和扩展,编译为可在更广泛的平台上支持的旧式JavaScript。当然,如果本机平台不支持ES6功能,Babel将无法完全提供帮助 - 但在许多情况下,polyfill缺少API以提供此功能例如Promise()。

Tips:
https://babeljs.io/repl 在线查看转换后的ES5代码

2.1.1 Babel配置

可以通过根目录中的.babelrc来配置我们的JS功能及使用的插件
RN的项目中我们主要使用了metro-react-native-babel-preset作为基本配置,并增加了@babel/plugin-proposal-decorators使用JS装饰器的功能

Tips: ReactNative 0.55以上的版本使用Babel7的版本,和以前的Babel配置有所不同具体请参考升级到Babel7

2.2 ES6

ECMAScript是用于实现JavaScript语言的语言规范。自ES5最初于2009年发布以来,ES6或ECMAScript 6是该语言的第一次重大更新。

现代JavaScript引擎中已经提供了许多ES6功能。使用Babel可以让我们访问更多功能,同时确保我们的JavaScript在更多平台上运行。React Native使用Babel启用ES6功能并确保跨平台一致性,因为您的JavaScript将在Android,iOS和其他平台上运行。

下面我将介绍一些重要的ES6使用功能点,如果想了解更多的功能可以参见ECMAScript 6 入门

2.2.1 块级作用域

let 和 const 命令
ES6 提出了两个新的声明变量的命令:letconst。其中,let完全可以取代var,因为两者语义相同,而且let没有副作用,没有变量提升的问题

const声明一个只读的常量。一旦声明,常量的值就不能改变。

2.2.2 rest参数

函数的扩展
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

  1. function add(...values) {
  2. let sum = 0;
  3. for (var val of values) {
  4. sum += val;
  5. }
  6. return sum;
  7. }
  8. add(2, 5, 3)

2.2.3 箭头函数

函数的扩展
ES6 允许使用“箭头”(=>)定义函数。
可以用箭头函数来定义匿名函数,他有2个重要的属性
1. 绑定在箭头函数的外部和内部this是相同的,这和普通的函数不一样,他可以在内部调用一个其他函数
2. 函数语法可能有所不同。如果函数只接受一个参数,则可以省略括号。任何其他数量的参数都需要括号。

  1. // 正常函数写法
  2. [1,2,3].map(function (x) {
  3. return x * x;
  4. });
  5. // 箭头函数写法
  6. [1,2,3].map(x => x * x);
  7. const numbers = (...nums) => nums;
  8. numbers(1, 2, 3, 4, 5)
  9. // [1,2,3,4,5]
  10. const headAndTail = (head, ...tail) => [head, tail];
  11. headAndTail(1, 2, 3, 4, 5)

2.2.4 扩展运算符

扩展运算符
扩展运算符可以轻松扩展数组、对象。这可以用于制作数组的浅拷贝,可选地将其他元素添加到副本中。

  1. const animals = ['cat', 'dog', 'moose']
  2. const newAnimals = [...animals]
  3. const lotsOfAnimals = [...animals, 'bear', 'mouse', 'donkey']

2.2.5 解构

解构
解构是一种方便的方法,可以同时从对象或数组中提取多个键,并将值分配给局部变量。

  1. const arr = ['one!', 'two!', 'three!', 'four!']
  2. const [one, two, ...rest] = arr
  3. const obj = {a: 'x', b: 'y', c: 'z'}
  4. const {a, b, c} = obj

2.2.6 默认参数

我们可以在函数声明中为函数参数指定默认值。如果是,则为参数分配默认值。undefined

  1. const printAnimal = (animal = 'cat') => {
  2. console.log(animal)
  3. }
  4. printAnimal() // cat
  5. printAnimal('dog') // dog

2.2.7 字符串模板

  1. $('#result').append(
  2. 'There are <b>' + basket.count + '</b> ' +
  3. 'items in your basket, ' +
  4. '<em>' + basket.onSale +
  5. '</em> are on sale!'
  6. );
  7. $('#result').append(`
  8. There are <b>${basket.count}</b> items
  9. in your basket, <em>${basket.onSale}</em>
  10. are on sale!
  11. `);

2.2.8 动态键值

在ES5中,对象文字键始终被解释为字符串。ES6允许我们使用方括号语法将计算值用作对象文字中的键

  1. const chosenAnimal = 'cat'
  2. const animals = {
  3. [`animal${chosenAnimal}`]: true,
  4. }
  5. console.log(animals.animalcat)

2.2.9 import 和 export

Module语法
与广泛使用的CommonJS模式相比,ES6提供了更高级的模块导入/导出模式。与旧版本相比,我们现在可以导出多个命名值。同样,我们可以导入多个命名值。module.exports = {...}
每个文件有一个默认导出,可以导入此导出值,而无需按名称引用它。必须命名每个其他导入和导出。

  1. // import the default export
  2. import React from 'react-native'
  3. // import other named exports
  4. import {View, Text, Image} from 'react-native'
  1. export default React
  2. export {View, Text, Image}

2.2.10 类

Class的基本语法
ES5中,类只是函数,实例方法分配给。ES6允许我们使用更简单的语法。MyFunction.prototype class
class为我们提供了内置的实例函数,静态函数和继承。
constructor`是一个特殊的函数,每次创建一个类实例时都会自动调用它。

  1. class Animal {
  2. constructor(name) {
  3. this.name = name
  4. }
  5. static beProud() {
  6. console.log('I AM AN ANIMAL')
  7. }
  8. printName() {
  9. console.log(this.name)
  10. }
  11. }
  12. const animal = new Animal('Cat')
  13. animal.printName() // Cat
  14. Animal.beProud() // I AM AN ANIMAL

2.2.10.1 继承

Class的继承
我们统计过extends关键词简单的继承。在从父级继承的类中,我们需要使用super()函数。在该子类的继承函数内,我们可以通过super调用父类的函数方法

  1. class Cat extends Animal {
  2. printName() {
  3. super.printName()
  4. console.log(`My name is ${this.name}`)
  5. }
  6. }

2.3 装饰器

2.3.1 类的修饰

修饰器
许多面向对象的语言都有修饰器(Decorator)函数,用来修改类的行为

  1. @testable
  2. class MyTestableClass {
  3. // ...
  4. }
  5. function testable(target) {
  6. target.isTestable = true;
  7. }
  8. MyTestableClass.isTestable // true

2.3.2 方法修饰

修饰器不仅可以修饰类,还可以修饰类的属性。

  1. class Math {
  2. @log
  3. add(a, b) {
  4. return a + b;
  5. }
  6. }
  7. function log(target, name, descriptor) {
  8. var oldValue = descriptor.value;
  9. descriptor.value = function() {
  10. console.log(`Calling ${name} with`, arguments);
  11. return oldValue.apply(this, arguments);
  12. };
  13. return descriptor;
  14. }
  15. const math = new Math();
  16. // passed parameters should get logged now
  17. math.add(2, 4);

2.4 异步函数

我们可以使用async在一个返回值是Promise类型函数名, 在继续执行此块中的代码之前,我们可以使用关键字await等待解析或拒绝承诺

在此函数方法内我们依然可以用try catch去处理错误

async函数

  1. const fetchData = async () => {
  2. return fetch('https://baidu.com/api/')
  3. }
  4. const printData = async () => {
  5. try {
  6. const json = await fetchData()
  7. console.log(json)
  8. } catch(e) {
  9. console.error("Problem", e)
  10. }
  11. }

2.5 JSX

一种 JavaScript 的语法扩展。 我们推荐在 React 中使用 JSX 来描述用户界面。JSX 乍看起来可能比较像是模版语言,但事实上它完全是在 JavaScript 内部实现的
JSX简介
深入JSX

2.5.1 一个简单的 JSX

  1. const element = <h1>Hello, world!</h1>

2.5.2 JSX 表达式

  1. function getGreeting(user) {
  2. if (user) {
  3. return <h1>Hello, {formatName(user)}!</h1>;
  4. }
  5. return <h1>Hello, Stranger.</h1>;
  6. }

2.5.3 JSX 属性

你可以使用引号来定义以字符串为值的属性:

  1. const element = <View tabIndex="0"/>

也可以使用大括号来定义以 JavaScript 表达式为值的属性:

  1. const element = <Image src={user.avatarUrl}/>

切记你使用了大括号包裹的 JavaScript 表达式时就不要再到外面套引号了。JSX 会将引号当中的内容识别为字符串而不是表达式

2.5.4 JSX 嵌套

如果 JSX 标签是闭合式的,那么你需要在结尾处用 />, 就好像 XML/HTML 一样。同时JSX也可以互相嵌套

  1. const element = (
  2. <View
  3. foo='hello'
  4. bar={baz}>
  5. <Text>42</Text>
  6. </View>
  7. );

2.5.5 React.createElement()

Babel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用。
上述的代码会转换如下

  1. var a = React.createElement(View, null);
  2. var b = React.createElement(
  3. View,
  4. {
  5. foo: 'hello',
  6. bar: baz },
  7. React.createElement(
  8. Text,
  9. null,
  10. '42'
  11. )
  12. )

2.6 TSX

jsx的Typescript实现称为jsx
TSX用法指南
转换路径: TSX->JSX->JS

  1. interface Props {
  2. foo: string;
  3. }
  4. class MyComponent extends React.Component<Props, {}> {
  5. render() {
  6. return <span>{this.props.foo}</span>
  7. }
  8. }

3. Components

React.Component
组件可以将UI切分成一些独立的、可复用的部件,这样你就只需专注于构建每一个单独的部件
通过声明要呈现的组件以及按什么顺序指定应用程序的整个UI。组件可以嵌套在其他组件中,形成树结构。顶级组件或树的根称为根组件,嵌套组件称为子组件。

3.1 React Components Api

3.1.1 Props

Components在constructor实例化时的属性叫做Props,在组件上我们可以通过this.props访问属性的值,组件中我们只能Components中的方法改变Props的值。
父元素可以随时改变子元素props,子元素可以通过shouldComponentUpdate()方法订阅父元素对Props的改变。

3.1.2 State

它只是用来控制这个组件本身自己的状态,我们可以用state来完成对行为的控制、数据的更新、界面的渲染,由于组件不能修改传入的props,所以需要记录自身的数据变化。

3.1.3 this.setState

我们可以通过this.setState()的方法去更新组件内的state。修改对象的键值的方式是无效的,我们必须要通过this.setState的方法

没有 state 的组件叫无状态组件(stateless component),设置了 state 的叫做有状态组件(stateful component)。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。

3.1.4 总结

以下给props和state做一个总结:
props用于定义外部接口,state用于记录内部状态
props的赋值在于外部使用组件,state的赋值在于组件内部
组件不应该改变props的值,而state存在的目的就是让组件来修改的

3.2 React 生命周期

组件具有生命周期:它们被实例化,装载,呈现,最终更新,卸载和销毁。生命周期通过提供简单,一致的抽象层来帮助管理不同平台API(iOS,Android)的复杂性。生命周期还允许您在每个步骤中可选地执行自定义代码,以便对渲染进行更精细的控制。

让我们看一下组件生命周期的每个阶段。
此处输入图片的描述

3.2.1 Mounting(开始渲染)

3.2.1.1 constructor(object props)

组件类已实例化。构造函数的参数是元素的初始值,由父元素指定。您可以选择通过this.setState为元素指定初始状态。此时UI还没有开始绘制

3.2.1.2 componentWillMount()

在第一次进行渲染之前,此方法仅调用一次。此时,仍然UI还没有开始绘制。

3.2.1.3 render() -> React Element

render方法必须返回一个React Element来渲染(或null,以便不渲染)。

3.2.1.4 componentDidMount()

第一次渲染后,此方法仅调用一次。此时,此元素的UI绘制已完成,并且可以通过直接操作进行访问。如果您需要进行异步API调用或执行延迟代码,通常应该在此方法中完成。

3.2.2 Updating(更新)

3.2.2.1 componentWillReceiveProps(object nextProps)

指父元素对组件的props或state进行了修改

3.2.2.2 shouldComponentUpdate(object nextProps, object nextState) -> boolean

一般用于优化,可以返回false或true来控制是否进行渲染的话进行下2步操作,false不会进行下去

3.2.2.3 componentWillUpdate(object nextProps, object nextState)

组件刷新前调用

3.2.2.4 render() -> React Element

render方法必须返回一个React Element来渲染(或null,以便不渲染)。

3.2.2.5 componentDidUpdate(object prevProps, object prevState)

会在更新发生后立即被调用(若shouldComponentUpdate()返回false)

3.2.3 Ummount(卸载)

3.2.3.1 componentWillUnmount

组件销毁阶段,例如可以在此阶段清除定时器

4. React Native Components 简介

React Native中文网

4.1 View

View
是构建RN项目最基本的元素之一,和我们编写HTML的DIV很像。不论在什么平台上,View都会直接对应一个平台的原生组件例如UIView, <div>, android.view等等。

4.2 Images

Images
Image是用来呈现图片的容器,我们可以从资源中加载图片也可以加载网络上的图片。
在APP中加载图片我们可以选择require('./test.png')RN会自动根据设备的尺寸加载
test.png, test@2x.png, 或者test@3x.png

引入在线的web图片因为不能提前知道图片的尺寸,图片无法拉伸。所以我们在初始化的时候需要制定Image中图片的尺寸。

  1. <Image
  2. style={styles.image}
  3. source={{uri: 'http://www.reactnativeexpress.com/logo.png'}}
  4. />
  5. const styles = StyleSheet.create({
  6. image: {
  7. width: 200,
  8. height: 200,
  9. },
  10. })

4.3 Text

一个用于显示文本的React Native组件,并且它也支持嵌套、样式,以及触摸处理。

4.4 Flexbox

RN的基本布局方式,组件使用flexbox指定元素的布局。
Flexbox示例
详细的教程查看Flex布局教程

属性 默认 选项 描述
flexDirection column row, column 主轴的方向
justifyContent flex-start flex-start, center, flex-end, space-around, space-between 元素的横轴对齐方式
alignItems stretch flex-start, center, flex-end, stretch 元素的纵轴对齐方式

4.5 ScrollView

ScrollViews用于滚动元素。最好用于30个元素以下的滚动,支持横向和竖向滚动。如果有大量的元素,最好使用ListView已获得更好的性能效果

4.6 Lists

列表与ScrollViews类似,但经过优化可回收元素并减少重新渲染以获得更好的性能。因此,API比ScrollView稍微复杂一些。React Native中的内置列表组件仍在不断发展,因此将来可以期待更高的稳定性和性能。
FlatList和SectionList是简单,高性能列表的新推荐列表组件。它们构建在VirtualizedList之上,VirtualizedList是一种高度灵活和优化的列表实现,通常不应直接使用。

4.6.1 FlatList

FlatList 继承VirtualizedList
FlatList DEMO
高性能的滚动列表组件,可用于大量可滚动内容,默认情况下每行都需要提供一个不重复的 key 属性。你也可以提供一个keyExtractor函数来生成 key。

4.6.2 SectionList

sectionlist 继承VirtualizedList
SectionList DEMO
类似FlatList,不过提供了节标题来分隔行组。

5. React Native Elements

React Native Elements
React Native Elements提供了一个跨平台的UI组件库

Tips:
1. Input用RN原生的Input组件更方便
2. 有些组件没有点击数据,需要自己在外面包装TouchableOpacity
3. 我们使用的是1.0.0 beta7版本,请不要看错文档!!!
4. React-Native-Cli工程需要react-native link react-native-vector-icons
5. 全局的样式通过theme.ts更改,更多的配置请参见ThemeProvider自定义样式

6. React Navigation

React Navigation

7. 数据流管理

7.1 Mobx

7.2 Redux

8. 网络

8.1 Axios

[31/webp

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注