ReactNative 进阶与调试
动画
Animated API
React Native 内置动画系统:
tsx
import { Animated } from 'react-native'
function FadeInView({ children }) {
const fadeAnim = useRef(new Animated.Value(0)).current
useEffect(() => {
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
useNativeDriver: true, // 启用原生驱动
}).start()
}, [fadeAnim])
return (
<Animated.View style={{ opacity: fadeAnim }}>
{children}
</Animated.View>
)
}import { Animated } from 'react-native'
function FadeInView({ children }) {
const fadeAnim = useRef(new Animated.Value(0)).current
useEffect(() => {
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
useNativeDriver: true, // 启用原生驱动
}).start()
}, [fadeAnim])
return (
<Animated.View style={{ opacity: fadeAnim }}>
{children}
</Animated.View>
)
}常见动画类型
tsx
// 弹簧效果
Animated.spring(value, {
toValue: 1,
friction: 3, // 摩擦力
tension: 40, // 张力
useNativeDriver: true,
}).start()
// 循环动画
Animated.loop(
Animated.sequence([
Animated.timing(anim, { toValue: 1, duration: 500, useNativeDriver: true }),
Animated.timing(anim, { toValue: 0, duration: 500, useNativeDriver: true }),
])
).start()
// 并行
Animated.parallel([
Animated.timing(fadeAnim, { toValue: 1, duration: 1000, useNativeDriver: true }),
Animated.timing(scaleAnim, { toValue: 2, duration: 1000, useNativeDriver: true }),
]).start()// 弹簧效果
Animated.spring(value, {
toValue: 1,
friction: 3, // 摩擦力
tension: 40, // 张力
useNativeDriver: true,
}).start()
// 循环动画
Animated.loop(
Animated.sequence([
Animated.timing(anim, { toValue: 1, duration: 500, useNativeDriver: true }),
Animated.timing(anim, { toValue: 0, duration: 500, useNativeDriver: true }),
])
).start()
// 并行
Animated.parallel([
Animated.timing(fadeAnim, { toValue: 1, duration: 1000, useNativeDriver: true }),
Animated.timing(scaleAnim, { toValue: 2, duration: 1000, useNativeDriver: true }),
]).start()插值
tsx
const rotate = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
})
const color = animatedValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: ['#ff0', '#f00', '#00f'],
})const rotate = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
})
const color = animatedValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: ['#ff0', '#f00', '#00f'],
})LayoutAnimation
自动动画布局变化:
tsx
import { LayoutAnimation, Platform, UIManager }
// Android 需要开启
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true)
}
function toggle() {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
setExpanded(!expanded)
}import { LayoutAnimation, Platform, UIManager }
// Android 需要开启
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true)
}
function toggle() {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
setExpanded(!expanded)
}手势响应
PanResponder
React Native 内置手势系统:
tsx
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: (_, gestureState) => {
console.log('移动中:', gestureState.dx, gestureState.dy)
},
onPanResponderRelease: (_, gestureState) => {
console.log('手势结束:', gestureState.vx, gestureState.vy)
},
})
).current
<View {...panResponder.panHandlers} style={styles.box} />const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: (_, gestureState) => {
console.log('移动中:', gestureState.dx, gestureState.dy)
},
onPanResponderRelease: (_, gestureState) => {
console.log('手势结束:', gestureState.vx, gestureState.vy)
},
})
).current
<View {...panResponder.panHandlers} style={styles.box} />react-native-gesture-handler
更强大的手势库:
bash
npm install react-native-gesture-handlernpm install react-native-gesture-handlertsx
import { GestureHandlerRootView, TapGestureHandler, PinchGestureHandler } from 'react-native-gesture-handler'
<GestureHandlerRootView style={{ flex: 1 }}>
<PinchGestureHandler onGestureEvent={onPinch}>
<View style={{ flex: 1 }} />
</PinchGestureHandler>
</GestureHandlerRootView>import { GestureHandlerRootView, TapGestureHandler, PinchGestureHandler } from 'react-native-gesture-handler'
<GestureHandlerRootView style={{ flex: 1 }}>
<PinchGestureHandler onGestureEvent={onPinch}>
<View style={{ flex: 1 }} />
</PinchGestureHandler>
</GestureHandlerRootView>权限申请
react-native-permissions
bash
npm install react-native-permissionsnpm install react-native-permissionstsx
import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions'
import { Platform } from 'react-native'
async function requestCameraPermission() {
const permission = Platform.select({
ios: PERMISSIONS.IOS.CAMERA,
android: PERMISSIONS.ANDROID.CAMERA,
})
const result = await request(permission)
if (result === RESULTS.GRANTED) {
console.log('权限已授予')
}
}import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions'
import { Platform } from 'react-native'
async function requestCameraPermission() {
const permission = Platform.select({
ios: PERMISSIONS.IOS.CAMERA,
android: PERMISSIONS.ANDROID.CAMERA,
})
const result = await request(permission)
if (result === RESULTS.GRANTED) {
console.log('权限已授予')
}
}Android 权限声明
xml
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />iOS 权限描述
xml
<!-- ios/AppName/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>需要使用相机</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要使用位置</string><!-- ios/AppName/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>需要使用相机</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要使用位置</string>调试
React Native DevTools
bash
# 开发菜单快捷键
# iOS: Cmd + D
# Android: Cmd + M
# 或摇晃设备# 开发菜单快捷键
# iOS: Cmd + D
# Android: Cmd + M
# 或摇晃设备开发菜单选项:
- Reload — 重载 JS(Cmd + R / R + R)
- Debug with Chrome — Chrome 调试器
- Show Element Inspector — 元素检查
- Toggle Fast Refresh — 快速刷新
Flipper
Facebook 官方调试工具:
bash
# 安装 Flipper(桌面端)
# 支持:
# - 网络请求日志
# - 数据库查看
# - 布局检查
# - JS 控制台
# - Crash 报告# 安装 Flipper(桌面端)
# 支持:
# - 网络请求日志
# - 数据库查看
# - 布局检查
# - JS 控制台
# - Crash 报告React DevTools
bash
npm install -g react-devtools
react-devtoolsnpm install -g react-devtools
react-devtoolsconsole 调试
tsx
// React Native 中 console.warn 显示在屏幕上
console.warn('可见的调试信息')
console.log('仅终端可见')// React Native 中 console.warn 显示在屏幕上
console.warn('可见的调试信息')
console.log('仅终端可见')打包发布
Android 签名与发布
bash
# 生成签名密钥
keytool -genkeypair -v -storetype PKCS12 \
-keystore my-release-key.keystore \
-alias my-alias -keyalg RSA -keysize 2048 \
-validity 10000
# 生成 AAB(推荐)
cd android
./gradlew bundleRelease
# 生成 APK
./gradlew assembleRelease# 生成签名密钥
keytool -genkeypair -v -storetype PKCS12 \
-keystore my-release-key.keystore \
-alias my-alias -keyalg RSA -keysize 2048 \
-validity 10000
# 生成 AAB(推荐)
cd android
./gradlew bundleRelease
# 生成 APK
./gradlew assembleRelease配置 gradle 签名:
gradle
// android/app/build.gradle
android {
signingConfigs {
release {
storeFile file('my-release-key.keystore')
storePassword '密码'
keyAlias 'my-alias'
keyPassword '密码'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}// android/app/build.gradle
android {
signingConfigs {
release {
storeFile file('my-release-key.keystore')
storePassword '密码'
keyAlias 'my-alias'
keyPassword '密码'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}iOS 打包 (Archive)
- Xcode 中选择 Product > Archive
- 配置签名证书和 Provisioning Profile
- Organizer 中上传 App Store Connect
Expo 发布
bash
# EAS Build(云端构建)
npx eas build --platform all
# OTA 更新
npx expo publish
# 提交商店
npx eas submit --platform ios
npx eas submit --platform android# EAS Build(云端构建)
npx eas build --platform all
# OTA 更新
npx expo publish
# 提交商店
npx eas submit --platform ios
npx eas submit --platform android常用插件
| 插件 | 用途 |
|---|---|
react-navigation | 导航 |
react-native-vector-icons | 图标库 |
react-native-camera | 相机 |
react-native-maps | 地图 |
react-native-push-notification | 推送通知 |
react-native-splash-screen | 启动屏 |
react-native-reanimated | 高性能动画 |
react-native-linear-gradient | 渐变背景 |
react-native-video | 视频播放 |
react-native-webview | WebView |
lottie-react-native | Lottie 动画 |
react-native-fast-image | 图片加载优化 |
Cao Note