Skip to content

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-handler
npm install react-native-gesture-handler
tsx
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-permissions
npm install react-native-permissions
tsx
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-devtools
npm install -g react-devtools
react-devtools

console 调试 ​

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) ​

  1. Xcode 中选择 Product > Archive
  2. 配置签名证书和 Provisioning Profile
  3. 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-webviewWebView
lottie-react-nativeLottie 动画
react-native-fast-image图片加载优化