基础知识
1. React Native 中导航的作用是什么?
1. 页面切换与状态管理
- React Native 中的导航组件(如
React Navigation
或React Native Navigation
)可以帮助开发者实现多个屏幕之间的切换,例如从列表页面跳转到详情页面。 - 它会自动处理页面的堆栈管理(Stack),记录用户的访问历史,支持前进和后退操作。
2. 提高用户体验
- 提供动画效果(如页面推入、淡入淡出等),让页面切换更加流畅自然。
- 支持手势操作,例如从屏幕边缘滑动返回上一页。
3. 参数传递与页面通信
- 导航可以在页面之间传递参数。例如,在一个产品列表页面点击某个商品后,导航到详情页面时传递商品的 ID。
Route
和Params
的配合可以让页面获取上下文信息。
4. 导航类型支持
- 支持多种导航类型:
- 栈式导航(Stack Navigator):模拟页面堆栈,按顺序推入或弹出页面。
- 底部标签导航(Bottom Tab Navigator):常用于应用主界面,提供不同功能的快速切换。
- 抽屉导航(Drawer Navigator):从屏幕侧边滑出菜单,适合显示附加功能。
- 嵌套导航:可以组合多种导航方式以满足复杂的应用需求。
5. 跨平台一致性
- React Native 的导航解决方案可以在 iOS 和 Android 平台上提供一致的体验,同时支持平台特定的导航行为。
6. 可扩展性
- 提供钩子(如
useNavigation
)和生命周期事件,方便开发者在导航过程中处理额外的逻辑,例如数据加载、权限检查等。 - 支持动态配置标题栏、按钮等 UI 元素。
2. React Native 中有哪些常用的导航库?它们的优缺点分别是什么?
在 React Native 中,常用的导航库主要有以下几个,每个库都具有各自的特点、优点和缺点,适用于不同的场景:
1. React Navigation
这是最常用的导航库之一,由社区主导开发,功能强大且灵活。
优点:
- 灵活性高:支持多种导航模式(栈导航、标签导航、抽屉导航等),且支持嵌套导航。
- 社区活跃:拥有广泛的文档、教程和社区支持。
- 跨平台一致性:在 iOS 和 Android 上表现一致。
- 高度可定制:可配置导航栏样式、动画、手势等。
- 支持动态功能:如动态标题、参数传递等。
缺点:
- 性能较低:使用 JavaScript 实现导航,在复杂场景下性能可能不如原生导航库。
- 配置复杂:功能多样化导致配置代码相对繁琐。
适用场景:
- 需要跨平台一致性且不要求极致性能的应用。
- 项目复杂度较高,需要多种导航模式。
2. React Native Navigation
由 Wix 开发,采用原生实现导航,性能表现优异。
优点:
- 性能优秀:使用原生代码实现导航,页面切换流畅。
- 原生外观:与平台原生导航行为完全一致。
- 支持复杂场景:能轻松实现复杂的嵌套导航和动态功能。
缺点:
- 学习成本较高:配置较复杂,需要了解更多的原生开发知识。
- 灵活性较低:自定义程度不如 React Navigation,但能满足大部分需求。
- 社区支持较弱:相比 React Navigation,文档和社区资源相对较少。
适用场景:
- 高性能要求的应用(如需要快速页面切换的复杂应用)。
- 对原生外观和行为要求较高的应用。
3. React Native Router Flux
基于 React Navigation 的封装,提供更简洁的 API。
优点:
- API 简单:对 React Navigation 进行了封装,简化了导航配置。
- 快速上手:适合初学者或需要快速实现导航功能的项目。
缺点:
- 不够灵活:对 React Navigation 的封装限制了部分高级功能的使用。
- 更新较慢:与 React Navigation 的版本更新存在一定的滞后性。
适用场景:
- 简单的项目或初学者使用。
- 不需要复杂导航逻辑的应用。
4. Native Stack Navigator
React Navigation 提供的性能优化选项,使用原生组件实现栈导航。
优点:
- 性能更好:与 React Navigation 的 JavaScript 栈导航相比,速度更快。
- 使用方便:仍然遵循 React Navigation 的 API 和生态。
缺点:
- 功能有限:只适用于栈导航场景,灵活性较低。
适用场景:
- 只需要栈导航,且对性能要求较高的应用。
5. Expo Router
基于 React Navigation,采用文件系统路由的导航方案(类似 Next.js)。
优点:
- 文件路由系统:通过文件夹结构定义导航路径,直观且易维护。
- 集成度高:适用于 Expo 项目,配置简单。
缺点:
- 适用范围有限:对非 Expo 项目支持较差。
- 灵活性较低:某些复杂场景可能不如手动配置导航灵活。
适用场景:
- 使用 Expo 构建的项目,且追求快速开发。
总结对比:
导航库 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
React Navigation | 灵活、社区活跃、多种导航模式 | 性能稍差、配置复杂 | 需要高灵活性的跨平台应用 |
React Native Navigation | 性能好、原生体验 | 学习曲线陡峭、社区资源较少 | 高性能、原生外观需求高 |
React Native Router Flux | 简单易用 | 功能受限 | 简单项目或初学者 |
Native Stack Navigator | 性能好、兼容 React Navigation 生态 | 功能有限 | 性能要求高的栈导航应用 |
Expo Router | 文件路由直观、集成方便 | 灵活性低、适用范围有限 | 使用 Expo 的快速开发项目 |
3. 如何在 React Native 中实现路由跳转?
在 React Native 中,实现路由跳转通常需要使用导航库(如 React Navigation)。以下是一个完整的实现过程,包括设置导航器和实现页面跳转的步骤。
1. 安装 React Navigation 和相关依赖
运行以下命令安装 React Navigation 和必需的依赖:
# 安装核心库
npm install @react-navigation/native
# 安装导航器所需依赖
npm install react-native-screens react-native-safe-area-context react-native-gesture-handler react-native-reanimated react-native-vector-icons
# 安装栈导航
npm install @react-navigation/stack
确保在项目的 index.js
文件中添加以下代码(仅需一次配置):
import 'react-native-gesture-handler';
2. 设置导航容器
创建一个导航容器并配置路由。以下以 栈导航(Stack Navigator) 为例:
创建 App.js
文件:
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
3. 创建页面组件
创建 HomeScreen.js
:
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const HomeScreen = ({ navigation }) => {
return (
<View style={styles.container}>
<Text style={styles.title}>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details', { itemId: 42 })}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 24,
fontWeight: 'bold',
},
});
export default HomeScreen;
创建 DetailsScreen.js
:
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const DetailsScreen = ({ route, navigation }) => {
const { itemId } = route.params || {};
return (
<View style={styles.container}>
<Text style={styles.title}>Details Screen</Text>
<Text>Item ID: {itemId}</Text>
<Button title="Go Back" onPress={() => navigation.goBack()} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 24,
fontWeight: 'bold',
},
});
export default DetailsScreen;
4. 路由跳转的实现
常用的导航方法:
navigation.navigate(name, params)
- 跳转到指定页面,可传递参数。
- 示例:
navigation.navigate('Details', { itemId: 42 });
navigation.goBack()
- 返回上一页。
- 示例:
navigation.goBack();
navigation.push(name, params)
- 将指定页面推入栈中,即使当前页面已经是目标页面,也会再次创建。
- 示例:
navigation.push('Details', { itemId: 100 });
navigation.replace(name, params)
- 替换当前页面,不会保留返回历史。
- 示例:
navigation.replace('Home');
navigation.popToTop()
- 返回到栈顶页面。
- 示例:
navigation.popToTop();
5. 接收路由参数
在目标页面中,通过 route.params
接收路由参数。例如:
const DetailsScreen = ({ route }) => {
const { itemId } = route.params || {};
return <Text>Item ID: {itemId}</Text>;
};
6. 自定义页面标题
可以通过 options
自定义页面标题:
<Stack.Screen
name="Details"
component={DetailsScreen}
options={{ title: 'Detail Page' }}
/>
也可以在页面组件中动态设置标题:
React.useLayoutEffect(() => {
navigation.setOptions({ title: 'Custom Title' });
}, [navigation]);
完整示例代码结构
App.js
screens/
- HomeScreen.js
- DetailsScreen.js
4. 什么是堆栈(Stack)、选项卡(Tab)和抽屉(Drawer)导航?它们的使用场景有哪些?
在 React Native 中,堆栈(Stack)、选项卡(Tab)、和抽屉(Drawer)导航是最常见的三种导航模式,每种都有其特点和适用场景:
1. 堆栈导航(Stack Navigation)
定义:
堆栈导航模拟了浏览器的导航历史或页面栈的行为。用户可以通过“压入”新页面进入下一级页面,或通过“弹出”返回上一级页面。
特点:
- 具有“前进”和“返回”的功能,常用于页面之间的线性跳转。
- 每次导航会将新页面加入到堆栈顶部(类似函数调用栈)。
- 典型页面切换动画(如从右侧滑入、从左侧滑出)。
使用场景:
- 页面之间有明确的层级关系,例如:
- 列表页跳转到详情页。
- 登录页跳转到主页面。
- 用户可能需要返回到之前的页面。
代码示例:
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
2. 选项卡导航(Tab Navigation)
定义:
选项卡导航通过底部或顶部的标签(Tab)切换页面,每个标签对应一个页面。标签导航通常显示多个并列的功能或页面。
特点:
- 页面的切换不会影响其他页面的状态(页面保持加载状态)。
- 用户可快速在不同页面间切换。
- 支持图标和文本标签,常见于底部导航栏。
使用场景:
- 应用有多个主要功能模块,用户需要频繁在模块之间切换,例如:
- 电商应用的“首页”、“分类”、“购物车”、“我的”。
- 社交应用的“消息”、“好友”、“动态”、“设置”。
代码示例:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
3. 抽屉导航(Drawer Navigation)
定义:
抽屉导航是一种从屏幕边缘滑出侧边菜单的导航方式,菜单中列出不同页面的导航项。
特点:
- 左滑或点击菜单按钮时,侧边栏会滑出显示菜单。
- 适合页面功能较多但标签不适合显示在屏幕上的情况。
- 菜单可以包含嵌套导航。
使用场景:
- 应用需要提供较多的功能页面,但用户不需要频繁切换,例如:
- 设置页面。
- 企业管理系统的功能模块导航。
- 需要在一个主页面的基础上提供附加功能,例如:
- 地图应用的“图层选择”、“导航模式”。
代码示例:
import { createDrawerNavigator } from '@react-navigation/drawer';
const Drawer = createDrawerNavigator();
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
导航模式对比与选择
导航模式 | 特点 | 适用场景 |
---|---|---|
堆栈导航 | 线性导航,支持页面的前进与返回,动画流畅。 | 需要上下级页面跳转的应用,如列表到详情页、表单页面导航等。 |
选项卡导航 | 并列导航,适合显示应用的主要功能模块,支持页面保持状态。 | 需要用户频繁切换模块的应用,如社交、电商、新闻类应用的功能模块。 |
抽屉导航 | 隐藏式菜单,适合功能较多但不常用的页面导航,菜单可以嵌套。 | 功能丰富且主页面占用屏幕空间较多的应用,如地图、企业管理系统或多模块设置界面。 |
综合场景
在复杂应用中,可能需要结合使用这些导航模式。例如:
- 电商应用:
- 底部选项卡:显示主要功能模块(首页、分类、购物车、我的)。
- 堆栈导航:从列表页跳转到详情页,或从购物车跳转到结算页面。
- 抽屉导航:从侧边打开“帮助中心”、“关于我们”等功能。
导航行为
1. 如何在导航中监听路由变化?
在 React Native 中,监听路由变化通常需要借助 React Navigation 提供的钩子或事件订阅机制。这可以帮助开发者在页面切换时执行特定的逻辑,如统计分析、更新状态或触发动画。
方法 1:使用 useFocusEffect
钩子
useFocusEffect
是 React Navigation 提供的一个钩子,专门用于处理页面聚焦时的逻辑。
示例代码:
import React from 'react';
import { View, Text } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
const HomeScreen = () => {
useFocusEffect(
React.useCallback(() => {
console.log('HomeScreen is focused');
return () => {
console.log('HomeScreen is unfocused');
};
}, [])
);
return (
<View>
<Text>Home Screen</Text>
</View>
);
};
export default HomeScreen;
特点:
- 在页面被导航至时触发逻辑。
- 返回一个清理函数,当页面离开焦点时触发。
方法 2:使用 useNavigationState
钩子
useNavigationState
钩子允许你访问导航器的状态,可以用来监控路由变化。
示例代码:
import React from 'react';
import { View, Text } from 'react-native';
import { useNavigationState } from '@react-navigation/native';
const HomeScreen = () => {
const state = useNavigationState(state => state);
React.useEffect(() => {
console.log('Current route name:', state.routes[state.index].name);
}, [state]);
return (
<View>
<Text>Home Screen</Text>
</View>
);
};
export default HomeScreen;
特点:
- 获取当前导航栈的状态。
- 可以判断当前活跃的路由。
方法 3:使用 addListener
订阅事件
通过 navigation.addListener
可以监听导航事件,例如 focus
和 blur
。
示例代码:
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
const HomeScreen = ({ navigation }) => {
useEffect(() => {
const unsubscribeFocus = navigation.addListener('focus', () => {
console.log('HomeScreen is focused');
});
const unsubscribeBlur = navigation.addListener('blur', () => {
console.log('HomeScreen is unfocused');
});
return () => {
unsubscribeFocus();
unsubscribeBlur();
};
}, [navigation]);
return (
<View>
<Text>Home Screen</Text>
</View>
);
};
export default HomeScreen;
特点:
- 事件可以单独订阅和清理。
- 适用于类组件和函数组件。
方法 4:使用全局 onStateChange
NavigationContainer
提供了 onStateChange
属性,可以在导航器状态发生变化时触发全局监听。
示例代码:
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer
onStateChange={(state) => {
const currentRoute = state.routes[state.index];
console.log('Current route:', currentRoute.name);
}}
>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
特点:
- 全局监听导航状态变化。
- 不需要在每个页面单独设置监听。
方法 5:使用 useRoute
钩子获取当前路由
通过 useRoute
可以获取当前路由对象,但不会自动监听变化。需要结合 useEffect
来实现逻辑。
示例代码:
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
import { useRoute } from '@react-navigation/native';
const HomeScreen = () => {
const route = useRoute();
useEffect(() => {
console.log('Route params:', route.params);
}, [route.params]);
return (
<View>
<Text>Home Screen</Text>
</View>
);
};
export default HomeScreen;
特点:
- 适合监听路由参数的变化。
- 不适合全局路由监听。
总结
方法 | 适用场景 |
---|---|
useFocusEffect | 页面聚焦时触发逻辑,推荐用于页面级的事件处理(如数据刷新)。 |
useNavigationState | 监听导航器状态变化,适合需要动态判断当前路由的场景。 |
navigation.addListener | 精确监听页面的 focus 或 blur 事件,适用于特定页面状态管理。 |
onStateChange | 全局导航状态变化监听,适合统计分析等全局场景。 |
useRoute | 获取当前路由对象,适合监听路由参数的变化。 |
2. 如何禁用或自定义返回行为?
以下是几种常见的禁用或自定义返回行为的方法:
1. 使用 navigation.goBack()
来自定义返回行为
如果你希望在某个页面按下返回按钮时执行自定义操作,而不是直接返回上一个页面,可以使用 navigation.goBack()
结合条件来决定是否执行返回行为。
示例代码:
import React from 'react';
import { Button, Alert, View } from 'react-native';
const DetailsScreen = ({ navigation }) => {
const handleGoBack = () => {
// 可以在这里自定义逻辑,例如确认返回或执行其他操作
Alert.alert(
"Confirm",
"Do you really want to go back?",
[
{ text: "Cancel", style: "cancel" },
{ text: "Yes", onPress: () => navigation.goBack() }
]
);
};
return (
<View>
<Button title="Go Back" onPress={handleGoBack} />
</View>
);
};
export default DetailsScreen;
特点:
- 通过自定义事件来控制返回行为。
- 可以实现弹出确认框或执行额外逻辑。
2. 使用 navigation.pop()
来控制返回行为
如果你想跳过多个页面返回,可以使用 pop()
来指定返回到特定的页面,而不是简单地返回到上一个页面。
示例代码:
const handleGoBack = () => {
// 返回到距离当前页面两层的页面
navigation.pop(2);
};
3. 禁用物理返回按钮(Android)
在 Android 中,用户可以通过设备的物理返回按钮返回上一个页面。如果你想禁用这个按钮,可以使用 BackHandler
来拦截物理返回按钮的事件。
示例代码:
import React, { useEffect } from 'react';
import { BackHandler, Alert, View } from 'react-native';
const DetailsScreen = () => {
useEffect(() => {
const backAction = () => {
Alert.alert("Hold on!", "Are you sure you want to exit?", [
{
text: "Cancel",
onPress: () => null,
style: "cancel"
},
{ text: "YES", onPress: () => BackHandler.exitApp() }
]);
return true; // 返回 `true` 来拦截默认返回行为
};
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
backAction
);
// 清理事件监听器
return () => backHandler.remove();
}, []);
return <View>{/* 页面内容 */}</View>;
};
export default DetailsScreen;
特点:
- 你可以根据需要显示确认对话框来确定是否退出或禁用返回。
- 在组件卸载时清理事件监听器。
4. 使用 useFocusEffect
来控制返回行为
如果你希望根据页面的聚焦状态自定义返回行为,可以使用 useFocusEffect
钩子来监听页面是否被聚焦,并在聚焦时禁用返回按钮或进行其他操作。
示例代码:
import React, { useEffect } from 'react';
import { BackHandler, Alert, View } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
const DetailsScreen = () => {
useFocusEffect(
React.useCallback(() => {
const backAction = () => {
Alert.alert("Hold on!", "Are you sure you want to exit?", [
{ text: "Cancel", style: "cancel" },
{ text: "YES", onPress: () => BackHandler.exitApp() }
]);
return true; // 拦截返回事件
};
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
backAction
);
// 清理事件监听器
return () => backHandler.remove();
}, [])
);
return <View>{/* 页面内容 */}</View>;
};
export default DetailsScreen;
特点:
- 通过
useFocusEffect
可以监听页面的聚焦状态,自定义聚焦时的返回行为。 - 适合根据页面状态动态启用或禁用返回按钮。
5. 使用 createStackNavigator
中的 gestureEnabled
属性来禁用滑动返回
如果你希望禁用页面的滑动返回(例如在 iOS 中的滑动返回),可以在 createStackNavigator
中设置 gestureEnabled: false
。
示例代码:
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();
const App = () => {
return (
<Stack.Navigator screenOptions={{ gestureEnabled: false }}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
);
};
export default App;
特点:
- 禁用 iOS 中的滑动返回手势。
- 适用于需要完全自定义导航行为的场景。
总结
-
自定义返回行为:
- 使用
navigation.goBack()
或navigation.pop()
来自定义返回逻辑。 - 结合条件判断和用户交互来控制返回行为。
- 使用
-
禁用物理返回按钮:
- 使用
BackHandler
拦截并自定义物理返回按钮的行为。
- 使用
-
禁用滑动返回手势:
- 使用
gestureEnabled: false
禁用滑动返回手势(适用于 iOS)。
- 使用
3. React Navigation 如何处理深度链接(Deep Linking)?
在 React Native 中,React Navigation 提供了对深度链接(Deep Linking)的支持,使得应用能够响应外部URL,并将用户导航到特定的屏幕或内容。深度链接通常用于处理外部应用、网页或通知中的链接,直接引导用户到应用中的特定页面。
React Navigation 中深度链接的配置和处理
React Navigation 的深度链接处理主要依赖于以下几个步骤:
1. 配置深度链接的目标 URL 格式
首先,你需要定义一个 URL 模式,这个模式描述了应用的深度链接的结构。可以通过在导航容器(NavigationContainer
)中配置 linking
属性来设置深度链接的处理规则。
基本配置
假设我们有一个应用,其中包含主页(Home
)和详情页(Details
)。你可以这样配置深度链接:
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
const Stack = createStackNavigator();
const linking = {
prefixes: ['myapp://'], // 设置协议
config: {
screens: {
Home: '', // 默认首页
Details: 'details/:id', // 详情页面,URL 中传递参数 id
},
},
};
function App() {
return (
<NavigationContainer linking={linking}>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
解释:
prefixes
:指定支持的 URL 协议,例如myapp://
,表示只有以myapp://
开头的 URL 才会触发应用的导航。config
:映射 URL 路径和应用中的屏幕。例如,Details
屏幕的 URL 为myapp://details/:id
,id
是路径参数,可以在屏幕组件中访问。
2. 处理 URL 中的参数
在深度链接中,URL 的路径参数(如 details/:id
)可以传递到目标屏幕。你可以通过 route.params
获取这些参数。
示例:
假设用户访问 myapp://details/123
,我们可以在 DetailsScreen
中获取到 id=123
。
const DetailsScreen = ({ route }) => {
const { id } = route.params;
return (
<View>
<Text>Details Screen</Text>
<Text>Item ID: {id}</Text>
</View>
);
};
3. 处理 iOS 和 Android 的深度链接
在 React Native 中,除了在 React Navigation 中配置深度链接,你还需要在原生部分进行配置。对于 iOS 和 Android,它们的深度链接处理方式稍有不同。
iOS 配置
在 iOS 中,你需要在 Info.plist
文件中注册应用支持的 URL 类型:
- 打开
ios/[your-project]/Info.plist
。 - 添加以下配置:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string> <!-- 配置协议 -->
</array>
</dict>
</array>
Android 配置
在 Android 中,你需要在 AndroidManifest.xml
中注册 URL 协议:
- 打开
android/app/src/main/AndroidManifest.xml
。 - 添加以下内容:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" /> <!-- 配置协议 -->
</intent-filter>
</activity>
这样,当用户点击 myapp://details/123
时,Android 和 iOS 都能够启动你的应用,并将其导航到对应的页面。
4. 监听 URL 和更新导航状态
React Navigation 在应用打开时会自动解析深度链接,并将用户导航到对应的页面。如果你需要监听 URL 的变化,可以使用 Linking
API 来处理。
监听深度链接事件:
import { Linking, useLinking } from '@react-navigation/native';
useEffect(() => {
const handleDeepLink = (event) => {
console.log(event.url); // 输出当前的 URL
};
// 监听 deep link 事件
Linking.addEventListener('url', handleDeepLink);
// 清理事件监听器
return () => {
Linking.removeEventListener('url', handleDeepLink);
};
}, []);
5. 使用深度链接打开特定页面
如果你想在应用中某个时刻手动触发深度链接,直接导航到某个页面,可以使用 Linking.openURL()
。
import { Linking } from 'react-native';
const openDeepLink = () => {
Linking.openURL('myapp://details/123'); // 打开详情页
};
总结
功能 | 实现方式 |
---|---|
配置深度链接协议和路径 | 使用 linking 配置对象,定义支持的 URL 协议和页面路径映射。 |
访问 URL 参数 | 通过 route.params 获取深度链接中传递的参数。 |
配置 iOS 和 Android 支持的 URL | 在 iOS 的 Info.plist 和 Android 的 AndroidManifest.xml 中配置 URL 协议。 |
监听 URL 变化 | 使用 Linking.addEventListener 或 useLinking 钩子来监听深度链接事件。 |
手动触发深度链接 | 使用 Linking.openURL() 来手动打开指定的深度链接。 |
下文预告
《React Native 性能优化》