- Published on
React Native 基础组件与样式化
React Native (RN) 作为一个使用 React 构建原生移动应用的框架,虽然共享了 React 的组件化、声明式 UI 等核心思想,但其渲染目标是移动设备的原生 UI 控件,而非浏览器的 DOM。这一根本性的差异,决定了 RN 在基础组件的使用、样式化方法以及布局模型上,与 Web 开发存在着显著的不同。
核心基础组件
在 RN 中,所有 UI 都是由原生组件构成的。其中,View 和 Text 是构建任何界面的基础。
<View>: 这是构建 UI 时最基础的容器组件。它支持布局、样式化和触摸事件处理,其角色类似于 Web 开发中的<div>标签。<Text>: 这是一个用于显示文本的专用组件。
在 React Native 中,所有需要被渲染的文本内容,都必须被包裹在 <Text> 组件之内。将裸文本直接放置在 <View> 或其他组件中,会导致程序抛出错误。这是 RN 与 Web (HTML) 的一个核心区别。
React Native 中的样式化
RN 的样式化系统在概念上与 CSS 相似,但在语法和实现上存在关键差异。
样式定义:JavaScript 对象
所有样式都通过 JavaScript 对象来定义,而非独立的 .css 文件。样式属性的命名遵循驼峰式命名法 (camelCase),例如 backgroundColor 对应 Web CSS 中的 background-color。
无单位尺寸系统:密度无关像素
在 RN 中,所有的尺寸(如 width, height, margin)都使用无单位的数字。这个数字代表的是密度无关像素 (Density-Independent Pixels, DP)。
DP 是一种抽象的单位,它能够确保 UI 元素在不同像素密度的设备屏幕上,展现出一致的物理尺寸。RN 会在底层根据设备的像素比率 (PixelRatio),自动将 DP 转换为真实的物理像素 (PX)。
物理像素 = DP 值 × PixelRatio
样式应用方式
- 内联样式 (Inline Styles): 可以直接将样式对象传递给组件的
style属性,适用于简单的、一次性的样式。
<Text style={{ color: 'blue', fontSize: 16 }}>Hello, World!</Text>
StyleSheet.create(最佳实践):StyleSheet.create方法用于创建集中管理的、经过优化的样式表对象。
StyleSheet.create 的优势- 性能优化: 样式对象在创建后会被赋予一个唯一的 ID,并只通过原生桥 (Bridge) 传递一次。在后续渲染中,只需传递这个 ID 即可,避免了重复创建和传递整个样式对象所带来的开销。
- 代码组织: 将样式与组件的渲染逻辑分离,提高了代码的可读性和可维护性。
- 静态验证: 可以在开发阶段对样式属性的拼写和值进行验证,提前发现错误。
- 样式数组 (Style Arrays):
style属性可以接收一个由样式对象组成的数组。数组中靠后的样式会覆盖靠前的样式,这为实现条件样式和动态样式提供了极大的便利。
import { StyleSheet, Text, View } from 'react-native';
// 使用 StyleSheet.create 创建样式表
const styles = StyleSheet.create({
container: {
padding: 16,
},
text: {
fontSize: 18,
color: 'black',
},
highlightedText: {
color: 'tomato',
fontWeight: 'bold',
},
});
function MyComponent({ isHighlighted }) {
return (
<View style={styles.container}>
{/* 使用样式数组来应用条件样式 */}
<Text style={[styles.text, isHighlighted && styles.highlightedText]}>
This text might be highlighted.
</Text>
</View>
);
}
默认布局模型:Flexbox
React Native 默认使用 Flexbox 进行布局,所有 <View> 元素天生就是一个 Flex 容器。但其默认值与 Web 端的 Flexbox 存在一些关键差异。
flexDirection: RN 的默认主轴方向是'column'(从上到下),而 Web 是'row'(从左到右)。这是最根本的区别,它更符合移动应用从上到下的典型布局模式。flex:flex属性在 RN 中只接受一个数字,它等同于 Web CSS 中的flex-grow,flex-shrink: 1和flex-basis: 0%的组合。flex: 1是最常用的样式,它意味着元素将占据所有可用的剩余空间。
可交互组件
Button vs. Pressable
Button: RN 内置的<Button>组件会渲染出对应平台的原生按钮(iOS 和 Android 的外观不同)。它的优点是简单易用,但缺点是可定制性极差,几乎无法修改其样式。TouchableOpacity&Pressable: 为了构建自定义的按钮和交互元素,开发者通常使用这两个组件。TouchableOpacity: 一个简单的封装,当用户触摸时,会将其子组件的透明度 (opacity) 降低,产生一个视觉反馈。可以通过activeOpacity属性控制按压时的透明度。Pressable(现代推荐): 这是新一代的、功能更强大的交互封装组件。它提供了对按压状态 (pressed state) 的精细控制,允许你根据不同的交互阶段(如onPressIn,onPressOut)来动态地改变样式。
Pressable 构建自定义按钮import { Pressable, Text, StyleSheet } from 'react-native';
const CustomButton = ({ onPress, title }) => (
<Pressable
onPress={onPress}
// style 属性可以接收一个函数,根据按压状态返回不同样式
style={({ pressed }) => [
styles.button,
{
backgroundColor: pressed ? 'rgb(210, 230, 255)' : 'dodgerblue',
},
]}>
<Text style={styles.buttonText}>{title}</Text>
</Pressable>
)
const styles = StyleSheet.create({
button: {
padding: 12,
borderRadius: 8,
alignItems: 'center',
},
buttonText: {
color: 'white',
fontSize: 16,
},
});