contactpicker api仅chrome 108+支持,需检测'contacts' in navigator && 'select' in navigator.contacts并降级;调用必含name字段,返回值为字符串数组,权限拒绝后不可恢复。

Chrome 108+ 才能用 ContactPicker API
这个 API 目前(2024 年中)仅在 Chrome 108 及以上桌面版(Windows/macOS/Linux)和 Android Chrome 中可用,Safari、Firefox、Edge 全都不支持。调用 navigator.contacts.select() 会直接抛出 TypeError: navigator.contacts is undefined —— 不是代码写错了,是浏览器根本不认这个对象。
实操建议:
- 必须先检测支持性:
if ('contacts' in navigator && 'select' in navigator.contacts) - 不支持时得降级:比如用
<input type="email">手动输入,或引导用户复制粘贴联系人信息 - Android 端需额外申请
CONTACTS权限(通过Permissions API),否则调用直接被拒绝
navigator.contacts.select() 的参数必须带 name 字段
API 要求至少请求一个字段,且 name 是唯一强制项;其他如 email、tel、address 都是可选的。漏掉 name 会导致 Promise 永远 pending,控制台也不报错,非常难排查。
常见错误写法:navigator.contacts.select(['email']) → 无效,会卡住
正确写法示例:
const props = ['name', 'email', 'tel'];
navigator.contacts.select(props, { multiple: true })
.then(contacts => {
console.log(contacts); // [{ name: ['张三'], email: ['zhang@example.com'], tel: ['138...'] }]
})
.catch(err => console.error(err.name)); // 'AbortError' 或 'NotAllowedError'
-
multiple: true允许选多个,但 Android 上目前仍只支持单选(实际表现和false一样) - 返回的每个
contact对象里,字段值都是字符串数组(即使只有一个值),别直接当字符串用 - 字段名大小写敏感,必须用小写:
'email'✅,'Email'❌
用户拒绝权限后,下次调用不会再次弹窗
一旦用户点「拒绝」或「阻止」,navigator.contacts.select() 后续调用会立刻 reject,Promise 返回 NotAllowedError,且不会再触发选择器界面。这和地理位置等权限不同——它没有“询问”状态,只有“允许”或“拒绝”两个终态。
实操建议:
- 首次调用前,最好先用
navigator.permissions.query({ name: 'contacts' })检查当前状态(state可能是'granted'、'denied'或'prompt') - 如果已是
denied,就别再试了,直接走降级逻辑 - 没有浏览器 API 能重置该权限,用户必须手动进 chrome://settings/content/contacts 清除站点权限
返回的 name 是数组,且顺序不可靠
contact.name 返回的是字符串数组,例如 ['李四', 'Lisi'],但规范没定义哪个是姓、哪个是名、哪个是拼音。Chrome 当前实现把通讯录里“显示名称”字段原样拆成数组(按空格或分号),结果因系统设置、导入来源差异极大。
别这么写:const firstName = contact.name[0];
更稳妥的做法:
- 优先展示整个
contact.name.join(' ')作为显示名 - 如需结构化解析,应结合
givenName和familyName字段(需在 select 参数中显式声明,并非所有设备都返回) - 注意:iOS 导入的联系人常无
givenName,而 Android 原生通讯录可能有但不填全
真实场景里,依赖 name 数组下标取值大概率出错,这点容易被忽略。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











