Skip to content

RN 内置基础组件

在上一章,我们已经对 RN 有了一个最基本的了解。接下来我们继续挖掘 RN 的其他内容。

打开 RN 的官网,可以看到官方文档中核心分为 4 个部分,分别是:

在上一章节《RN 快速入门》中,我们相当于将 Guides(向导)部分的内容已经完成了。本章节我们就着重来看 Components(内置组件)和 API(接口文档)。

image-20220606161209673

在 RN 中,内置组件整体可以分为三大类:

其中核心组件的数量是最多的。核心组件有一个特点,就是全平台通用。根据最终编译的目标平台,核心组件会被编译为对应平台的组件。如下图:

image-20220606161243452

而核心组件又可以根据其用途分为以下几大类:

本小节我们就先来看一下第一类组件——基础组件。基础组件大致如下:

Image 组件#

Image 是一个图片展示组件,其作用类似于 AndroidImageView 或者 iOSUIImageViewImage 组件支持多种类型的图片显示,包括网络图片、静态资源、base64 图片格式。

要使用 Image 组件加载图片,只需要设置 source 属性即可,如果加载的是网络图片,还需要添加 uri 标识以及手动指定图像的尺寸。

目前,Image 组件支持的图片格式有 PNG、JPG、JPEG、BMP、GIF、WebP 以及 PSD。不过,在默认情况下 Android 是不支持 GIFWebP 格式图片的,如果需要添加这两种图片格式的支持,需要在 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 种:

下面的示例演示了不同属性值之间视觉效果上的区别:

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

需要注意的是,TextInputAndroid 中默认有一个底边框且存在内边距。如果想让它看起来和 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 App

Switch 组件#

SwitchRN 提供的一个状态切换的组件,俗称开关组件,主要用来对开和关两个状态进行切换。

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