# 简介
React Native (简称 RN) 是 Facebook 于 2015 年 4 月开源的跨平台移动应用开发框架,是 Facebook 早先开源的 JS 框架 React 在原生移动应用平台的衍生产物,支持 iOS 和安卓 两大平台。RN 使用 Javascript 语言,类似于 HTML 的 JSX,以及 CSS 来开发移动应用,因此熟悉 Web 前端开发的技术人员只需很少的学习就可以进入移动应用开发领域。
# React Native 适合哪些场景
没有完美的跨端技术,只有适合的场景。脱离适用场景去谈跨端技术没有什么意义 。
# 适合业务更新迭代较快的团队
React Native 上手成本较低。对前端同学来说,React Native 和前端技术生态重合度很高, 学习成本很低 ;对客户端同学来说,React Native 省去了大量的编译耗时 ,并且自带跨端光环, 一份源码可以同时编译成 Android 和 iOS 原生应用,并发布到安卓和苹果应用商店上 。
所以,在一些业务迭代快的团队中,使用 React Native 跨端方案 不仅能够节约开发成本,还能带来接近原生的体验和性能 。
# 既要支持动态更新,又要支持复杂业务的场景
在国内,无论大公司、小公司都钟情于 应用的动态更新 。因为动态更新 能降低产品的试错成本 。如果产品策略有调整,可以立马上线,线上有小问题也可以快速修复。但能够 既满足动态更新,又能跨端,还能满足复杂业务需求的只有 JavaScript 语言 。
目前几个主流的跨端框架,除了 React Native 之外,还有小程序、Weex、Flutter。但小程序只能让你的应用运行在别人的 App 上,Weex 最终未能大规模流行起来,而 Flutter 使用的语言是 Dart 而非 JavaScript,并不能很好支持动态更新 。
换句话说,除了基于 JavaScript 的自研框架外, 目前能够既支持动态更新,又支持复杂业务的主流移动跨端框架只有使用 JavaScript 开发的 React Native 。
# 为什么选择 React Native 做你的跨端方案
# React Native 是一个非常流行的跨端框架,开发者认可度很高。
react-native 框架每周的下载次数,已经从 5 年前的不到 10 万次,到现在超过了 80 万次,5 年时间翻了 8 倍之多。
对于个人而言,强大的生态意味着很多功能都不用自己写,从社区拿来用就行,这极大地降低了开发成本。你可以在社区中选择最适合你业务的技术工具,比如状态管理、路由、动画、工具库和原生扩展等等。对于企业来说,使用 React Native 这类成熟框架开发移动应用成本更低,风险也更低,企业也更愿意招聘相关开发者。
# React Native 能让你得到技术上的延伸
如果你是一个前端工程师,已经掌握 JavaScript、React 的相关技术,那么对 React Native 的学习,可以让你了解到那些独属于 Android 和 iOS 原生平台的特性。
比如,你可以亲手尝试使用 WebView 容器来加载 Web 页面,甚至你还可以用 WebView 中的 JavaScript 去调用 React Native 中的 JavaScript,把 Native 暴露给 React Native 的支付能力再暴露给 Web,这样你能更加深刻地体会到 Hybrid 的实现原理。
# 入门基础
# 函数式组件与 Class 组件
你可以在 React 中使用函数式组件或 Class 组件。最开始只有 Class 组件能够使用 state ,但自从有了 React Hooks API, 你可以为函数组件添加 state 和很多其它的功能。
Hooks API 是 React Native 0.59 提供的新特性,Hooks 是一种面向未来的编写 React 组件的方式,因此 推荐优先使用函数组件 。
-
函数式组件
flex布局再RN中垂直的,这里的justifyContent代表垂直方向,alignItems代表水平方向import React from "react"; import { Text, View } from "react-native"; const HelloWorldApp = () => { return ( <View style={{ flex: 1, justifyContent: "center", alignItems: "center", }} > <Text>Hello, world!</Text> </View> ); }; export default HelloWorldApp; -
Class 组件
import React, { Component } from "react"; import { Text, View } from "react-native"; class HelloWorldApp extends Component { render() { return ( <View style={{ flex: 1, justifyContent: "center", alignItems: "center", }} > <Text>Hello, world!</Text> </View> ); } } export default HelloWorldApp;
# 原生组件与核心组件
# 原生组件
在 Android 开发中是使用 Kotlin 或 Java 来编写视图;在 iOS 开发中是使用 Swift 或 Objective-C 来编写视图。在 React Native 中,则使用 React 组件通过 JavaScript 来调用这些视图。在运行时,React Native 为这些组件创建相应的 Android 和 iOS 视图。由于 React Native 组件就是对原生视图的封装,因此使用 React Native 编写的应用外观、感觉和性能与其他任何原生应用一样。我们将这些平台支持的组件称为 原生组件 。
React Native 允许您为 Android 和 iOS 构建自己的 Native Components(原生组件),以满足您开发应用程序的独特需求。
React Native 还包括一组基本的,随时可用的原生组件,您可以使用它们来构建您的应用程序。这些是 React Native 的 核心组件 。
# 核心组件
React Native 具有许多核心组件,从表单控件到活动指示器,应有尽有。比如: <View> 在 Android 中为 <ViewGroup> ,在 IOS 中为 <UIView>
-
案例 1:使用基本组件
import React from "react"; import { View, Text, Image, ScrollView, TextInput } from "react-native"; const App = () => { return ( // ScrollView:可以包含多个组件和视图的通用滚动容器,对应Web中的div <ScrollView> // Text:对应Web中的p <Text>Some text</Text> // View:对应不滚动的div <View> <Text>Some more text</Text> // 图片,对应Web中的img <Image source={{ uri: "https://reactnative.dev/docs/assets/p_cat2.png", }} style={{ width: 200, height: 200 }} /> </View> // 输入框,defaultValue是默认值 // TextInput:对应Web中的<input type="text"> <TextInput style={{ height: 40, borderColor: "gray", borderWidth: 1, }} defaultValue="You can type in me" /> </ScrollView> ); }; export default App; -
案例 2:使用 state
import React, { useState } from "react"; import { Button, Text, View } from "react-native"; const Cat = (props) => { const [isHungry, setIsHungry] = useState(true); return ( <View> <Text> I am {props.name}, and I am {isHungry ? "hungry" : "full"}! </Text> <Button onPress={() => { setIsHungry(!isHungry); }} title={isHungry ? "Pour me some milk, please!" : "Thank you!"} /> </View> ); }; const Cafe = () => { return ( <> <Cat name="Munkustrap" /> <Cat name="Spot" /> </> ); }; export default Cafe; -
案例 3:使用 TextInput
import React, { useState } from "react"; import { Text, TextInput, View } from "react-native"; export default function PizzaTranslator() { const [text, setText] = useState(""); // onChangeText的属性,此属性接受一个函数,而此函数会在文本变化时被调用。另外还有一个名为onSubmitEditing的属性,会在文本被提交后(用户按下软键盘上的提交键)调用。 return ( <View style={{ padding: 10 }}> <TextInput style={{ height: 40 }} placeholder="Type here to translate!" onChangeText={(text) => setText(text)} defaultValue={text} /> <Text style={{ padding: 10, fontSize: 42 }}> {text .split(" ") .map((word) => word && "🍕") .join(" ")} </Text> </View> ); } -
案例 4:使用滚动视图
-
ScrollView是一个通用的可滚动的容器,你可以在其中放入多个组件和视图,而且这些组件并不需要是同类型的。ScrollView 不仅可以垂直滚动,还能水平滚动(通过horizontal属性来设置)。 -
代码
import React from "react"; import { Image, ScrollView, Text } from "react-native"; const logo = { uri: "https://reactnative.dev/img/tiny_logo.png", width: 64, height: 64, }; export default App = () => ( <ScrollView horizontal={true}> // horizontal={true} 设置为水平滚动,默认为false(垂直滚动) <Text style={{ fontSize: 96 }}>Scroll me plz</Text> <Image source={logo} /> <Image source={logo} /> <Text style={{ fontSize: 96 }}>If you like</Text> <Image source={logo} /> <Image source={logo} /> <Text style={{ fontSize: 96 }}>Scrolling down</Text> <Image source={logo} /> <Image source={logo} /> <Text style={{ fontSize: 96 }}>What's the best</Text> <Image source={logo} /> <Image source={logo} /> <Text style={{ fontSize: 96 }}>Framework around?</Text> <Image source={logo} /> <Image source={logo} /> <Text style={{ fontSize: 80 }}>React Native</Text> </ScrollView> ); -
ScrollViews 可以通过使用
pagingEnabled属性来允许使用滑动手势对视图进行分页,在Android上也可以利用ViewPager组件水平滑动视图。 -
在 iOS 上包含单个子元素的 ScrollViews 可以允许用户对内容进行缩放。通过设置
maximumZoomScale和minimumZoomScale两者的属性,您的用户能够利用捏合以及扩大手势来放大或缩小。 -
ScrollView适合用来显示数量不多的滚动元素。放置在ScrollView中的所有组件都会被渲染,哪怕有些组件因为内容太长被挤出了屏幕外。如果你需要显示较长的滚动列表,那么应该使用功能差不多但性能更好的 FlatList(长列表)组件。
-
-
案例 5:使用长列表
React Native 提供了几个适用于展示长列表数据的组件,一般而言我们会选用FlatList或是SectionListFlatList 组件用于显示一个垂直的滚动列表,
其中的元素之间结构近似而仅数据不同。FlatList 更适于长列表数据,且元素个数可以增删。
和 ScrollView 不同的是,FlatList 并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。FlatList 组件
必须的两个属性是data和renderItem。data 是列表的数据源,而renderItem 则从数据源中逐个解析数据,然后返回一个设定好格式的组件来渲染。下面的例子创建了一个简单的 FlatList,并预设了一些模拟数据。首先是初始化 FlatList 所需的 data,其中的每一项(行)数据之后都在 renderItem 中被渲染成了 Text 组件,最后构成整个 FlatList。
-
FlatList 代码
import React from "react"; import { FlatList, StyleSheet, Text, View } from "react-native"; const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 22, }, item: { padding: 10, fontSize: 18, height: 44, }, }); const FlatListBasics = () => { return ( <View style={styles.container}> <FlatList data={[ { key: "Devin" }, { key: "Dan" }, { key: "Dominic" }, { key: "Jackson" }, { key: "James" }, { key: "Joel" }, { key: "John" }, { key: "Jillian" }, { key: "Jimmy" }, { key: "Julie" }, ]} renderItem={({ item }) => ( <Text style={styles.item}>{item.key}</Text> )} /> </View> ); }; export default FlatListBasics;如果要渲染的是一组
需要分组的数据,也许还带有分组标签的,那么SectionList将是个不错的选择 -
SectionList 代码
import React from "react"; import { SectionList, StyleSheet, Text, View } from "react-native"; const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 22, }, sectionHeader: { paddingTop: 2, paddingLeft: 10, paddingRight: 10, paddingBottom: 2, fontSize: 14, fontWeight: "bold", backgroundColor: "rgba(247,247,247,1.0)", }, item: { padding: 10, fontSize: 18, height: 44, }, }); const SectionListBasics = () => { return ( <View style={styles.container}> <SectionList sections={[ { title: "D", data: ["Devin", "Dan", "Dominic"] }, { title: "J", data: [ "Jackson", "James", "Jillian", "Jimmy", "Joel", "John", "Julie", ], }, ]} // 这里的item是data中的数据 renderItem={({ item }) => <Text style={styles.item}>{item}</Text>} renderSectionHeader={({ section }) => ( <Text style={styles.sectionHeader}>{section.title}</Text> )} keyExtractor={(item, index) => index} /> </View> ); }; export default SectionListBasics;
-