Contact Picker API:让用户分享选定的联系人,而非整个通讯录
发布于
一句话: Contact Picker API 让 web 应用通过浏览器原生的选择器界面,请求用户从通讯录中挑选一个或多个联系人——只分享用户选中的具体联系人和字段,绝不会分享完整通讯录。
为何用选择器而非批量访问
Section titled “为何用选择器而非批量访问”Contact Picker API 允许用户从其联系人列表中选择条目,并将所选条目的有限详情分享给网站
或应用。navigator.contacts 暴露一个 ContactsManager,ContactsManager.select() 会
打开一个由浏览器控制的选择器;用户决定选择哪些联系人,以及释放所请求的哪些属性
(name、email、tel、address、icon)。MDN 列出的常见用例包括:选择要通过邮件或
聊天应用联系的联系人、为 VOIP 通话选择联系人的电话号码,或发现哪些联系人已在使用某个
社交平台。
const props = ['name', 'email', 'tel'];const opts = { multiple: true };
async function getContacts() { try { const contacts = await navigator.contacts.select(props, opts); handleResults(contacts); } catch (ex) { // select() 可能抛出异常——见下方「可能出错的地方」。 }}props 列出要请求的字段;getProperties() 会报告当前浏览器实际支持这些字段中的哪些,
让网站在调用 select() 之前调整请求:
async function checkProperties() { const supported = await navigator.contacts.getProperties(); if (supported.includes('email')) { // 可以安全地在 props 中请求 "email"。 }}- 安全上下文。 MDN 记载
select()仅在安全上下文(HTTPS)中可用。 - 用户手势。 MDN 说明
select()需要用户手势,返回的Promise才会 resolve。 - 不适用于 Web Worker。 MDN 指出 Contact Picker API 不会暴露在
WorkerNavigator上。
MDN 将 Contact Picker API 标记为实验性技术,不属于 Baseline,因为它无法在一些最广泛使用
的浏览器中运行。在生产环境中依赖它之前,请查阅 MDN 上 Contact_Picker_API 与
ContactsManager 页面的浏览器兼容性表。
async function shareContacts(props, opts) { if (!('contacts' in navigator && 'ContactsManager' in window)) { // 此处不支持——回退到手动输入表单。 return null; } return navigator.contacts.select(props, opts);}可能出错的地方
Section titled “可能出错的地方”MDN 的 select() 参考文档记载了该调用可能抛出/拒绝的错误条件:
TypeError—— 请求的properties列表为空,或包含浏览器不支持的属性。InvalidStateError—— 调用发生在非顶层浏览上下文中、已有一个联系人选择器处于打开 状态,或选择器本身启动失败。SecurityError——select()并非由用户激活触发。
MDN 自己的示例用 try/catch 来处理这些情况;由于 select() 返回一个 Promise,也可以
用 .catch() 处理。
- 在调用
select()之前,先用'contacts' in navigator && 'ContactsManager' in window做特性检测。 - 只在真实的用户手势中调用
select()——MDN 记载它需要用户手势才能 resolve。 - 在依赖返回字段之前,先调用
getProperties()确认浏览器实际会返回哪些字段。 - 处理
TypeError、InvalidStateError、SecurityError——可以用try/catch,也 可以对返回的 Promise 使用.catch()。 - 准备好手动输入的回退界面——MDN 将该 API 标记为非 Baseline。
- 不要假设访问权限会持续存在——每次请求都需要用户重新执行一次操作。