Skip to content
React Native 核心组件与样式
React Native 的界面由一组内置核心组件构成,这些组件最终映射到 iOS 和 Android 的原生视图。理解它们的行为,是搭建任何界面的基础。
View 与 Text
View 的布局行为
View 是最基础的容器组件,Android 侧对应 android.view.View,iOS 侧对应 UIView。它负责容纳其他组件并基于 Flexbox 规则排列——Flexbox 将在后续单独说明,这里先关注 View 自身的尺寸行为。
在默认的 flexDirection: 'column'(纵向主轴)下,View 在交叉轴方向(水平方向)撑满父容器宽度,而在主轴方向(纵向)高度由子元素内容决定,不会自动占满剩余空间。
tsx
import {View, Text} from 'react-native';
const Example = () => (
<View>
<View style={{height: 50, backgroundColor: 'powderblue'}} />
<View style={{height: 50, backgroundColor: 'skyblue'}} />
<View style={{height: 50, backgroundColor: 'steelblue'}} />
</View>
);外层 View 没有显式高度,其高度为三个色块高度之和(150),宽度则撑满屏幕。内层三个 View 各自高度 50、横向撑满。View 本身透明,只有设置了背景色或边框才会产生可见区域。
如果将外层 View 改为不包含固定高度子元素的情况,高度会进一步收缩:
tsx
<View style={{backgroundColor: '#eee'}}>
<Text>一行文本</Text>
</View>这个 View 的高度仅等于文本行高加上内边距(此处未设 padding,所以贴合内容),并非占满父容器。只有当容器获得 flex: 1 时,它才会在主轴方向占据剩余可用空间——这是 Flexbox 分配规则决定的,不是 View 的默认行为。
View 不具备滚动能力,内容超出边界会被裁剪。这与 ScrollView 的行为形成对比。
Text 的嵌套与样式覆盖
Text 负责将字符串渲染为原生文本视图。React Native 中的文字只能放置在 <Text> 组件内部,不可以直接写在 <View> 中。
Text 支持嵌套。子 Text 会继承父 Text 的样式,并可覆盖特定属性:
tsx
<Text style={{fontSize: 18, color: 'black'}}>
这是普通文本,
<Text style={{fontWeight: 'bold', color: 'red'}}>
这是加粗红色文本
</Text>
</Text>同一段文字中后半部分变为红色粗体。子组件指定的属性覆盖继承来的属性,未指定的继续沿用父级值。这种覆盖仅限于 Text 嵌套链内部。View 的样式不会被 Text 继承——整个样式系统更接近对象的直接赋值,而非基于选择器的级联。
嵌套的 Text 表现为行内元素,不会主动换行。多行文本可通过单独的 Text 配合 numberOfLines 等属性处理。
TextInput
TextInput 接收用户文本输入,遵循受控组件模式:通过 value 指定显示文本,通过 onChangeText 回调接收输入变更,由父组件更新 state 驱动值写回。
tsx
import {useState} from 'react';
import {TextInput} from 'react-native';
const InputExample = () => {
const [text, setText] = useState('');
return (
<TextInput
value={text}
onChangeText={setText}
placeholder="输入用户名"
keyboardType="default"
/>
);
};placeholder 在未输入时显示提示文字。keyboardType 控制虚拟键盘类型,常用值包括 'default'、'numeric'、'email-address'、'phone-pad'。不同平台弹出的键盘布局略有差异,但 API 层面已统一,业务代码通常不需做平台判断。
受控模式下,若将 value 固定写死(例如 <TextInput value="hello" />),用户输入不会改变显示内容,这与 Web 的 <input> 行为一致。如需默认值但不完全控制,可使用 defaultValue 属性代替 value。
ScrollView
内容超出屏幕时,ScrollView 提供滚动能力。它会一次性渲染所有子组件,无论是否处于可视区域。因此 ScrollView 适合有限长度的内容(设置页、表单等),不适合渲染长列表,长列表应使用 FlatList。
ScrollView 自身可接收样式属性,但作用于内容区的样式应通过 contentContainerStyle 设置:
tsx
import {ScrollView, Text} from 'react-native';
const ScrollExample = () => (
<ScrollView contentContainerStyle={{padding: 16}}>
<Text>第一段内容...</Text>
<Text>第二段内容...</Text>
</ScrollView>
);contentContainerStyle 影响包裹所有子元素的内部容器,而直接给 ScrollView 设置 style={{padding: 16}} 会影响滚动区域本身,效果不同。
输入框位于 ScrollView 中时,键盘弹起后系统会将焦点输入框自动滚至可视区域。配合 keyboardShouldPersistTaps="handled" 可以避免点击键盘或切换输入框时事件被 ScrollView 吞掉:
tsx
<ScrollView keyboardShouldPersistTaps="handled">
<TextInput placeholder="用户名" />
<TextInput placeholder="密码" />
</ScrollView>StyleSheet
StyleSheet.create 与内联样式
样式以 JavaScript 对象描述,属性名采用驼峰命名。例如 CSS 的 background-color 对应 backgroundColor,font-size 对应 fontSize。
样式可直接写在组件的 style 属性中,也可以用 StyleSheet.create 创建样式对象:
tsx
import {StyleSheet} from 'react-native';
const styles = StyleSheet.create({
container: {
padding: 16,
backgroundColor: '#fff',
},
title: {
fontSize: 20,
fontWeight: '600',
},
});两种写法渲染结果等价。StyleSheet.create 的额外作用包括:将样式对象注册到原生端,通过 ID 引用以减少 JS 与原生之间的通信开销;提供静态类型检查,避免拼写错误。动态样式不可避免要使用内联对象,但静态定义的大多数样式推荐使用 StyleSheet.create。
样式数组与样式继承
组件的 style 属性可以接收数组,按顺序合并各成员样式,后面覆盖前面的同名字段:
tsx
<Text style={[styles.title, {color: 'red'}]}>红色标题</Text>这一行为类似 Object.assign,是实现样式叠加的主要手段。数组中既可放入 StyleSheet.create 创建的对象,也可放入内联对象。
React Native 没有样式继承——父组件的样式不会传递给子组件(Text 嵌套内部的样式继承是例外)。每个组件需要显式指定自己的样式。这一点与 Web 的 CSS 继承模型差异明显。
Flexbox 布局
React Native 使用 Flexbox 作为布局模型。默认主轴方向为纵向(flexDirection: 'column'),子元素由上至下堆叠排列。
flexDirection 与 justifyContent
flexDirection 决定主轴方向:
'column'(默认):主轴垂直,子元素纵向排列。'row':主轴水平,子元素横向排列。
justifyContent 控制子元素在主轴上的分布:
'flex-start':靠主轴起点(默认)。'center':居中。'flex-end':靠主轴终点。'space-between':两端对齐,中间均匀分布。'space-around':每个元素两侧间距相等。
tsx
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Text>左</Text>
<Text>中</Text>
<Text>右</Text>
</View>当 flexDirection 为 'row' 时,主轴是水平方向,justifyContent 控制水平分布。
alignItems 与 flex
alignItems 控制子元素在交叉轴(垂直于主轴)上的对齐:
'stretch'(默认):拉伸填满交叉轴。'flex-start':交叉轴起点对齐。'center':交叉轴居中。'flex-end':交叉轴终点对齐。
主轴为 'column' 时,交叉轴是水平方向,alignItems: 'center' 使子元素水平居中;主轴为 'row' 时,交叉轴是垂直方向,alignItems: 'center' 使子元素垂直居中。
flex 属性定义组件在主轴方向上如何分配剩余空间,取值为数字比值:
tsx
<View style={{flexDirection: 'row'}}>
<View style={{flex: 1, height: 50, backgroundColor: 'red'}} />
<View style={{flex: 2, height: 50, backgroundColor: 'blue'}} />
</View>红色块占 1/3 宽度,蓝色块占 2/3 宽度。flex 仅在父容器具有确定尺寸(设置了宽高或自身也有 flex 值)时生效。
静态登录界面
将上述组件与样式组合,可以构建一个静态登录界面,包含用户名输入、密码输入和登录按钮,纵向居中布局:
tsx
import React, {useState} from 'react';
import {
View,
Text,
TextInput,
TouchableOpacity,
ScrollView,
StyleSheet,
} from 'react-native';
const LoginScreen = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
return (
<ScrollView
contentContainerStyle={styles.container}
keyboardShouldPersistTaps="handled">
<Text style={styles.title}>登录</Text>
<TextInput
style={styles.input}
placeholder="用户名"
value={username}
onChangeText={setUsername}
keyboardType="default"
autoCapitalize="none"
/>
<TextInput
style={styles.input}
placeholder="密码"
value={password}
onChangeText={setPassword}
secureTextEntry
keyboardType="default"
/>
<TouchableOpacity style={styles.button} activeOpacity={0.8}>
<Text style={styles.buttonText}>登录</Text>
</TouchableOpacity>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 24,
backgroundColor: '#f5f5f5',
},
title: {
fontSize: 28,
fontWeight: '700',
textAlign: 'center',
marginBottom: 32,
color: '#333',
},
input: {
height: 48,
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 8,
paddingHorizontal: 12,
fontSize: 16,
backgroundColor: '#fff',
marginBottom: 16,
},
button: {
height: 48,
backgroundColor: '#4a90d9',
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
marginTop: 8,
},
buttonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
});
export default LoginScreen;关键点:
ScrollView作为外层容器,keyboardShouldPersistTaps="handled"保证键盘交互正常。contentContainerStyle设置flex: 1并配合justifyContent: 'center',将表单在屏幕中纵向居中。- 两个
TextInput通过value和onChangeText实现受控模式;密码框使用secureTextEntry隐藏输入。 TouchableOpacity提供点击反馈,样式由StyleSheet.create定义。- 所有布局行为均为 Flexbox 在主轴
'column'下的表现。
该界面具备完整静态表单的结构,后续可接入网络请求与状态管理,扩展为可用功能。
参考链接
- [1] https://developer.android.com/develop/ui/views/layout/declaring-layout?hl=zh-cn
- [2] https://developer.apple.com/cn/documentation/swiftui/building-layouts-with-stack-views
- [3] https://storybook.js.org/tutorials/intro-to-storybook/react/zh-CN/simple-component
- [4] https://developer.apple.com/cn/videos/play/wwdc2024/10146
