今天来了解一种能改善 Expo 应用体验的技术:
深层链接(Deep Link)
。
重点是如何通过深层链接跳转到指定页面,并用
查询参数
一并传递需要的数据。
你有没有点击过一个网站链接,结果直接打开了某个应用里的特定页面?
这就是深层链接。它可以从其他应用、网站、推送通知等外部入口,把用户直接带到应用内的指定内容或功能。
本文以 Expo Router 为例,逐步介绍如何在 Expo 项目中配置深层链接、在 URL 中添加查询参数,以及如何在目标页面读取和使用这些数据。
深层链接像 Web 上的 URL 一样,为应用分配可识别的地址,让用户从应用外部直接访问特定界面或功能。
没有深层链接时,点击链接可能只会打开应用首页,或者把用户带到应用商店。用户需要自己找到并打开应用,再经过几步操作才能抵达目标页面。
在购物应用中打开商品 ID 为 123 的详情页。
在新闻应用中显示“体育”分类的文章列表。
在地图应用中显示指定经纬度的位置。
这些情况可以用
查询参数
。在 URL 路径后加上问号,再用
key=value 的形式传入所需数据。多个参数用
& 分隔。
示例:myapp://products/detail?productId=123&category=electronics
myapp:// 是用于识别应用的 URL scheme。
products/detail 是应用内路径,对应商品详情页。
?productId=123&category=electronics 是查询参数,表示商品 ID 为 123,分类为电子产品。
有了查询参数,深层链接就能在把用户带到目标页面的同时,传入构建该页面所需的具体信息。
配置 Expo 深层链接(以 Expo Router 为例) 🔗
使用深层链接之前,需要先配置 Expo 项目。借助 Expo Router,这个过程很简单。
先为应用选择一个能唯一识别它的 URL scheme。
例如,应用名为“My Awesome App”时,可以使用“myawesomeapp”。在应用的
app.json 或
app.config.js 文件中设置。
app.json {
"expo" : {
"name" : "My Awesome App" ,
"slug" : "my-awesome-app" ,
"scheme" : "myawesomeapp" , // 여기에 원하는 스킴을 입력합니다.
"web" : {
"bundler" : "metro"
},
"plugins" : [
"expo-router" // Expo Router를 사용하고 있다면 이 플러그인이 필요합니다.
]
// ... 기타 설정 ...
}
}
该值会成为深层链接 URL 的开头,例如
myawesomeapp://...。建议选择与应用名称相关、又不容易与其他应用重复的名字。
使用 Expo CLI 构建项目后,scheme 会自动写入原生配置,即 iOS 的 Info.plist 和 Android 的 AndroidManifest.xml。
2. 利用 Expo Router 的文件结构 🔗
Expo Router 使用基于文件系统的路由。
app 目录下的文件结构会映射到 URL 路径。
例如,创建
app/products/detail.tsx 后,它对应的路径就是
myawesomeapp://products/detail。
查询参数直接加在路径后面即可,不需要为参数创建单独的文件。
深层链接可以用于推送通知、网站链接、营销邮件等应用外部的入口。要创建带查询参数的 URL,在既定的 scheme 和路径后加上 ?,再用 & 连接各组 key=value 即可。
跳转到商品 ID 为 456 的详情页:myawesomeapp://products/detail?productId=456
跳转到用户 alice 的个人资料页:myawesomeapp://users/profile?username=alice
在搜索结果页搜索 react native:myawesomeapp://search?query=react%20native(空格经过 URL 编码后可以写成 %20)
用户点击生成的 URL 后,Expo 应用会解析地址,跳转到对应页面,并把查询参数传给该页面组件。
读取深层链接参数(useLocalSearchParams) 🔗
现在来看看如何在应用的目标页面获取和使用深层链接中的查询参数。Expo Router 提供了
useLocalSearchParams Hook。
下面以从
app/products/detail.tsx 读取
productId 为例。
// 파일 경로: app/products/detail.tsx
import { useLocalSearchParams } from 'expo-router' ;
import React from 'react' ;
import { View, Text, StyleSheet } from 'react-native' ;
export default function ProductDetailScreen () {
// useLocalSearchParams 훅을 사용하여 현재 경로에 전달된 파라미터를 가져옵니다.
// 제네릭 타입을 사용하여 파라미터의 타입을 명시할 수 있습니다.
const params = useLocalSearchParams <{ productId ?: string ; category ?: string }>();
const productId = params.productId; // 'productId' 키로 값 추출
const category = params.category; // 'category' 키로 값 추출 (있다면)
console. log ( '전달받은 Product ID:' , productId);
console. log ( '전달받은 Category:' , category);
// productId를 사용하여 상품 정보를 불러오는 등의 로직 수행 가능
// useEffect(() => {
// if (productId) {
// fetchProductDetails(productId);
// }
// }, [productId]);
return (
< View style ={ styles.container } >
< Text style ={ styles.title } >상품 상세 페이지</ Text >
{ productId ? (
< Text >요청된 상품 ID: { productId } </ Text >
) : (
< Text >상품 ID가 전달되지 않았습니다.</ Text >
) }
{ category && ( // category 파라미터가 있을 경우 표시
< Text >카테고리: { category } </ Text >
) }
</ View >
);
}
const styles = StyleSheet. create ({
container: {
flex: 1 ,
justifyContent: 'center' ,
alignItems: 'center' ,
padding: 20 ,
},
title: {
fontSize: 24 ,
fontWeight: 'bold' ,
marginBottom: 20 ,
},
});
调用 useLocalSearchParams 后,会得到一个包含当前页面(路由)查询参数的对象。
在返回的对象(params)上,用参数名(例如 productId、category)作为键读取所需的值。
如果使用 TypeScript,可以用泛型 useLocalSearchParams<{ productId?: string; category?: string }>() 声明参数类型及可选性(?),提高类型安全性。查询参数以字符串形式传入,如果要按数字使用,可以通过 parseInt() 等方法转换。
用读到的值(productId)显示页面所需的数据,也可以用该 ID 向服务器请求详情,再执行后续操作。
🖐️
请尽量为应用选择独特的 scheme,以免与其他应用冲突。
在 Expo Go 或开发构建环境中,打开终端,用以下命令测试深层链接。命令可能因环境而略有不同。
# Android 에뮬레이터/기기
npx uri-scheme open myawesomeapp://products/detail?productId= 999 --android
# iOS 시뮬레이터/기기
npx uri-scheme open myawesomeapp://products/detail?productId= 999 --ios
在 iOS 模拟器中,也可以使用 Hardware → Open URL... 菜单。
在真机上,可以把 URL 输入备忘录或消息应用,再点击链接进行测试。
深层链接与查询参数可以让操作更顺畅,也让用户更容易使用应用中的具体功能。通过外部链接,可以将用户直接带到目标内容,并传入所需信息,从而减少操作步骤,鼓励用户参与。
使用 Expo Router 的
useLocalSearchParams Hook,就能方便地提取并使用通过深层链接传入的查询参数。