在上一章,我们已经对 RN 有了一个最基本的了解。接下来我们继续挖掘 RN 的其他内容。
打开 RN 的官网,可以看到官方文档中核心分为 4 个部分,分别是:
- Guides(向导)
- Components(内置组件)
- API(接口文档)
- Architecture(架构)
在上一章节《RN 快速入门》中,我们相当于将 Guides(向导)部分的内容已经完成了。本章节我们就着重来看 Components(内置组件)和 API(接口文档)。
在 RN 中,内置组件整体可以分为三大类:
- 核心组件
- Android 平台独有组件
- iOS 平台独有组件
其中核心组件的数量是最多的。核心组件有一个特点,就是全平台通用。根据最终编译的目标平台,核心组件会被编译为对应平台的组件。如下图:

而核心组件又可以根据其用途分为以下几大类:
- 基础组件
- 容器组件
- 列表组件
- 功能组件
本小节我们就先来看一下第一类组件——基础组件。基础组件大致如下:
- Image 组件
- TextInput 组件
- Button 组件
- Switch 组件
Image 组件#
Image 是一个图片展示组件,其作用类似于 Android 的 ImageView 或者 iOS 的 UIImageView。Image 组件支持多种类型的图片显示,包括网络图片、静态资源、base64 图片格式。
要使用 Image 组件加载图片,只需要设置 source 属性即可,如果加载的是网络图片,还需要添加 uri 标识以及手动指定图像的尺寸。
目前,Image 组件支持的图片格式有 PNG、JPG、JPEG、BMP、GIF、WebP 以及 PSD。不过,在默认情况下 Android 是不支持 GIF 和 WebP 格式图片的,如果需要添加这两种图片格式的支持,需要在 android/app/build.gradle 文件中添加以下的依赖:
dependencies { // If your app supports Android versions before Ice Cream Sandwich (API level 14) implementation 'com.facebook.fresco:animated-base-support:1.3.0'
// For animated GIF support implementation 'com.facebook.fresco:animated-gif:2.5.0'
// For WebP support, including animated WebP implementation 'com.facebook.fresco:animated-webp:2.5.0' implementation 'com.facebook.fresco:webpsupport:2.5.0'
// For WebP support, without animations implementation 'com.facebook.fresco:webpsupport:2.5.0'}API 文档地址:https://reactnative.dev/docs/image
使用 Image 组件时,有一个常用的属性 resizeMode,此属性用于控制当组件和图片尺寸不成比例时以何种方式调整图片的大小,对应的值有 5 种:
- cover:在保持图片宽高比的前提下缩放图片,直到宽度和高度都大于等于容器视图的尺寸。
- contain:在保持图片宽高比的前提下缩放图片,直到宽度和高度都小于等于容器视图的尺寸。
- stretch:拉伸图片且不维持图片的宽高比,直到宽度和高度都刚好填满容器。
- repeat:在维持原始尺寸的前提下,重复平铺图片直到填满容器。
- center:居中且不拉伸的显示图片。
下面的示例演示了不同属性值之间视觉效果上的区别:
import React, { Component } from 'react'import { Platform, StyleSheet, Image, Text, View } from 'react-native'
export default class ImageResizeMode extends Component { render() { let imageSource = require('./assets/ok.png')
return ( <View style={styles.container}> <Image style={[styles.image, { resizeMode: 'cover' }]} source={imageSource} /> <Text style={styles.text}>cover</Text>
<Image style={[styles.image, { resizeMode: 'contain' }]} source={imageSource} /> <Text style={styles.text}>contain</Text>
<Image style={[styles.image, { resizeMode: 'stretch' }]} source={imageSource} /> <Text style={styles.text}>stretch</Text>
<Image style={[styles.image, { resizeMode: 'repeat' }]} source={imageSource} /> <Text style={styles.text}>repeat</Text>
<Image style={[styles.image, { resizeMode: 'center' }]} source={imageSource} /> <Text style={styles.text}>center</Text> </View> ) }}
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, image: { width: 140, height: 110, backgroundColor: 'red', }, text: { justifyContent: 'center', fontSize: 24, },})TextInput 组件#
TextInput 是一个输入框组件,用于将文本内容输入到 TextInput 组件上。作为一个高频使用的组件,TextInput 支持自动拼写、自动大小写切换、占位默认字符设置以及多种键盘设置功能。
import React from 'react'import { View, StyleSheet, TextInput } from 'react-native'
const UselessTextInput = () => { const [text, onChangeText] = React.useState('Useless Text') const [number, onChangeNumber] = React.useState(null)
return ( <View style={styles.container}> <TextInput style={styles.input} onChangeText={onChangeText} placeholder="默认是字母键盘" value={text} /> <TextInput style={styles.input} onChangeText={onChangeNumber} value={number} placeholder="使用数字键盘" keyboardType="numeric" /> </View> )}
const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'stretch', justifyContent: 'center', }, input: { height: 40, margin: 12, borderWidth: 1, padding: 10, },})
export default UselessTextInput需要注意的是,TextInput 在 Android 中默认有一个底边框且存在内边距。如果想让它看起来和 iOS 上的效果尽量一致,则需要将 padding 的值设置为 0。
API 文档地址:https://reactnative.dev/docs/textinput
下面我们来看一个实际开发中使用到 TextInput 的案例——搜索框,代码如下:
import React, { useState } from 'react'import { TextInput, StyleSheet, Text, View } from 'react-native'
export default function SearchView() { const [text, setText] = useState('') const [show, isShow] = useState(false)
function showOption(newVal) { console.log(newVal, 'show') setText(newVal) isShow(true) }
function hideOption(newVal) { console.log(newVal, 'hide') setText(newVal) isShow(false) }
return ( <View style={styles.container}> <View style={styles.searchContainer}> <TextInput style={styles.inputStyle} returnKeyType="search" placeholder="请输入关键字" onChangeText={(val) => showOption(val)} value={text} /> <View style={styles.btnStyle}> <Text style={styles.search} onPress={() => alert(text)}> 搜索 </Text> </View> </View> {show ? ( <View style={[styles.resultStyle]}> <Text onPress={() => hideOption(text + '街')} style={styles.itemStyle} numberOfLines={1} > {text}街 </Text> <Text onPress={() => hideOption(text + '道路')} style={styles.itemStyle} numberOfLines={1} > {text}道路 </Text> <Text onPress={() => hideOption(80 + text + '车站')} style={styles.itemStyle} numberOfLines={1} > 80{text}车站 </Text> </View> ) : null} </View> )}
const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F5FCFF', paddingTop: 25, }, searchContainer: { height: 45, flexDirection: 'row', }, inputStyle: { height: 45, flex: 1, marginTop: 20, borderWidth: 1, marginLeft: 10, paddingLeft: 5, borderColor: '#ccc', borderRadius: 5, }, btnStyle: { width: 80, marginTop: 20, marginLeft: -5, marginRight: 10, borderBottomRightRadius: 5, borderTopRightRadius: 5, backgroundColor: '#23BEFF', height: 45, justifyContent: 'center', alignItems: 'center', }, search: { color: '#fff', fontSize: 15, fontWeight: 'bold', }, resultStyle: { marginTop: 20, marginLeft: 10, marginRight: 10, height: 200, borderColor: '#ccc', borderTopRightRadius: 5, borderTopLeftRadius: 5, }, itemStyle: { fontSize: 16, padding: 5, paddingTop: 10, paddingBottom: 10, borderWidth: 1, borderColor: '#ddd', borderTopWidth: 0, },})Button 组件#
Button 是一个最基本的按钮组件,可以在跨平台上很好地呈现,支持最低级别的定制。
API 文档地址:https://reactnative.dev/docs/button
import React from 'react'import { StyleSheet, Button, View, SafeAreaView, Text, Alert,} from 'react-native'
const Separator = () => <View style={styles.separator} />
const App = () => ( <SafeAreaView style={styles.container}> <View> <Text style={styles.title}> The title and onPress handler are required. It is recommended to set accessibilityLabel to help make your app usable by everyone. </Text> <Button title="Press me" onPress={() => Alert.alert('Simple Button pressed')} /> </View> <Separator /> <View> <Text style={styles.title}> Adjust the color in a way that looks standard on each platform. On iOS, the color prop controls the color of the text. On Android, the color adjusts the background color of the button. </Text> <Button title="Press me" color="#f194ff" onPress={() => Alert.alert('Button with adjusted color pressed')} /> </View> <Separator /> <View> <Text style={styles.title}> All interaction for the component are disabled. </Text> <Button title="Press me" disabled onPress={() => Alert.alert('Cannot press this one')} /> </View> <Separator /> <View> <Text style={styles.title}> This layout strategy lets the title define the width of the button. </Text> <View style={styles.fixToText}> <Button title="Left button" onPress={() => Alert.alert('Left button pressed')} /> <Button title="Right button" onPress={() => Alert.alert('Right button pressed')} /> </View> </View> </SafeAreaView>)
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', marginHorizontal: 16, }, title: { textAlign: 'center', marginVertical: 8, }, fixToText: { flexDirection: 'row', justifyContent: 'space-between', }, separator: { marginVertical: 8, borderBottomColor: '#737373', borderBottomWidth: StyleSheet.hairlineWidth, },})
export default AppSwitch 组件#
Switch 是 RN 提供的一个状态切换的组件,俗称开关组件,主要用来对开和关两个状态进行切换。
Switch 组件的用法比较简单,只需要给组件绑定 value 属性即可,这样它就是一个受控组件。如果需要改变组件的状态,则必须使用 onValueChange 方法来更新 value 的值。
API 文档地址:https://reactnative.dev/docs/switch
import React, { useState } from 'react'import { View, Switch, StyleSheet } from 'react-native'
const App = () => { const [isEnabled, setIsEnabled] = useState(false) const toggleSwitch = () => setIsEnabled((previousState) => !previousState)
return ( <View style={styles.container}> <Switch trackColor={{ false: '#767577', true: '#81b0ff' }} thumbColor={isEnabled ? '#f5dd4b' : '#f4f3f4'} ios_backgroundColor="#3e3e3e" onValueChange={toggleSwitch} value={isEnabled} /> </View> )}
const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', },})
export default App