ContactCard 联系人卡片 - Vant 4
📇 ContactCard 联系人卡片
📋 介绍
ContactCard 就像是你手机通讯录里的一张精美名片!✨ 它以优雅的卡片形式展示联系人信息,不仅颜值在线,功能也超级贴心。无论是添加新朋友的联系方式,还是编辑老朋友的信息,都能让你的联系人管理变得如丝般顺滑。就像有了一个贴心的通讯录管家,让每一次联系人操作都充满仪式感!🎭
📦 引入
通过以下方式来全局注册组件,更多注册方式请参考组件注册。
js
import { createApp } from'vue'; import { ContactCard } from'vant'; const app = createApp(); app.use(ContactCard);🎯 代码演示
➕ 添加联系人 - 新朋友入驻通讯录
想要为通讯录添加新成员?ContactCard 的添加模式就像是为新朋友准备的专属邀请函!🎉 一键点击,轻松开启联系人录入之旅。
html
js
import { showToast } from'vant'; exportdefault { setup() { constonAdd = () => showToast('新增'); return { onAdd, }; }, };✏️ 编辑联系人 - 老朋友信息更新
朋友换了新号码?搬了新家?ContactCard 的编辑模式就像是联系人信息的贴心管家!📝 让你轻松更新好友的最新动态,确保每次联系都能第一时间找到对的人。
html
js
import { ref } from'vue'; import { showToast } from'vant'; exportdefault { setup() { const tel = ref('13000000000'); const name = ref('张三'); constonEdit = () => showToast('edit'); return { tel, name, onEdit, }; }, };🔒 不可编辑 - 只读模式展示
有些联系人信息需要保持稳定?ContactCard 的只读模式就像是给重要联系人加了一层保护罩!🛡️ 既能清晰展示信息,又能防止误操作,让重要联系人信息安全无忧。
html
API
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 卡片类型,可选值为 edit | string | add |
| name | 联系人姓名 | string | - |
| tel | 联系人手机号 | string | - |
| add-text | 添加时的文案提示 | string | 添加联系人 |
| editable | 是否可以编辑联系人 | boolean | true |
Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| click | 点击时触发 | event: MouseEvent |
类型定义
组件导出以下类型定义:
ts
importtype { ContactCardType, ContactCardProps } from'vant';🎨 主题定制
样式变量
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件。
| 名称 | 默认值 | 描述 |
|---|---|---|
| --van-contact-card-padding | var(--van-padding-md) | - |
| --van-contact-card-add-icon-size | 40px | - |
| --van-contact-card-add-icon-color | var(--van-primary-color) | - |
| --van-contact-card-title-line-height | var(--van-line-height-md) | - |
🎯 最佳实践
📱 移动端适配建议
- 触摸友好 - 确保卡片区域足够大,方便手指点击
- 视觉层次 - 使用合适的字体大小和颜色对比度
- 加载状态 - 为网络请求添加加载提示
- 错误处理 - 优雅处理联系人信息获取失败的情况
🎨 界面设计技巧
vue
<template>
<!-- 推荐:添加过渡动画 -->
<transition name="contact-card" mode="out-in">
<ContactCard
:key="contactKey"
:type="cardType"
:name="contactName"
:tel="contactTel"
@click="handleCardClick"
class="smooth-card"
/>
</transition>
</template>
<style>
.contact-card-enter-active,
.contact-card-leave-active {
transition: all 0.3s ease;
}
.contact-card-enter-from {
opacity: 0;
transform: translateY(20px);
}
.contact-card-leave-to {
opacity: 0;
transform: translateY(-20px);
}
.smooth-card {
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
</style>🔄 状态管理建议
javascript
// 推荐:使用响应式数据管理联系人状态
const contactState = reactive({
isEditing: false,
isLoading: false,
contactInfo: {
name: '',
tel: '',
id: null
}
})
// 切换编辑状态
const toggleEditMode = () => {
contactState.isEditing = !contactState.isEditing
}
// 保存联系人信息
const saveContact = async () => {
contactState.isLoading = true
try {
await updateContactAPI(contactState.contactInfo)
showSuccessToast('保存成功')
contactState.isEditing = false
} catch (error) {
showFailToast('保存失败,请重试')
} finally {
contactState.isLoading = false
}
}💡 使用技巧
🎭 动态卡片类型
vue
<template>
<ContactCard
:type="dynamicType"
:name="contactName"
:tel="contactTel"
:editable="canEdit"
@click="handleClick"
/>
</template>
<script setup>
// 根据用户权限动态设置卡片类型
const dynamicType = computed(() => {
if (!contactName.value && !contactTel.value) {
return 'add'
}
return hasEditPermission.value ? 'edit' : 'add'
})
// 智能点击处理
const handleClick = () => {
if (dynamicType.value === 'add') {
// 跳转到添加联系人页面
router.push('/contact/add')
} else {
// 跳转到编辑联系人页面
router.push(`/contact/edit/${contactId.value}`)
}
}
</script>🔍 联系人搜索集成
vue
<template>
<div class="contact-search-container">
<Search
v-model="searchKeyword"
placeholder="搜索联系人"
@search="handleSearch"
/>
<div class="contact-list">
<ContactCard
v-for="contact in filteredContacts"
:key="contact.id"
type="edit"
:name="contact.name"
:tel="contact.tel"
@click="selectContact(contact)"
/>
<!-- 空状态 -->
<Empty
v-if="filteredContacts.length === 0"
description="暂无匹配的联系人"
/>
</div>
</div>
</template>
<script setup>
const searchKeyword = ref('')
const contacts = ref([])
// 过滤联系人
const filteredContacts = computed(() => {
if (!searchKeyword.value) return contacts.value
return contacts.value.filter(contact =>
contact.name.includes(searchKeyword.value) ||
contact.tel.includes(searchKeyword.value)
)
})
</script>📞 快捷操作集成
vue
<template>
<ContactCard
type="edit"
:name="contactName"
:tel="contactTel"
@click="showActionSheet"
/>
<ActionSheet
v-model:show="showActions"
:actions="contactActions"
@select="handleAction"
/>
</template>
<script setup>
const showActions = ref(false)
const contactActions = [
{ name: '拨打电话', icon: 'phone-o' },
{ name: '发送短信', icon: 'chat-o' },
{ name: '编辑联系人', icon: 'edit' },
{ name: '删除联系人', icon: 'delete-o', color: '#ee0a24' }
]
const showActionSheet = () => {
showActions.value = true
}
const handleAction = (action) => {
switch (action.name) {
case '拨打电话':
window.location.href = `tel:${contactTel.value}`
break
case '发送短信':
window.location.href = `sms:${contactTel.value}`
break
case '编辑联系人':
router.push(`/contact/edit/${contactId.value}`)
break
case '删除联系人':
confirmDelete()
break
}
}
</script>❓ 常见问题解决
🔧 卡片点击无响应?
问题:ContactCard 点击事件不触发 解决方案:
- 检查是否正确绑定了
@click事件 - 确认父容器没有阻止事件冒泡
- 验证 CSS 样式是否影响了点击区域
📱 移动端显示异常?
问题:在移动设备上卡片显示不正常 解决方案:
css
/* 确保移动端适配 */
.van-contact-card {
min-height: 60px;
touch-action: manipulation;
}
/* 防止长按选择文本 */
.van-contact-card * {
user-select: none;
-webkit-user-select: none;
}🎨 自定义样式不生效?
问题:CSS 变量修改后样式没有变化 解决方案:
- 确保在正确的作用域内设置 CSS 变量
- 使用
!important提高优先级(谨慎使用) - 检查是否有其他样式覆盖
🎨 设计灵感
🌈 主题风格建议
商务风格 - 简洁线条 + 深色配色
css--van-contact-card-padding: 20px; --van-contact-card-add-icon-color: #2c3e50;活泼风格 - 圆润边角 + 亮色配色
css--van-contact-card-padding: 16px; --van-contact-card-add-icon-color: #ff6b6b;极简风格 - 留白设计 + 单色配色
css--van-contact-card-padding: 24px; --van-contact-card-add-icon-color: #666;
🎯 交互设计建议
- 微动画 - 添加悬停和点击动画效果
- 状态反馈 - 清晰的加载和成功状态提示
- 手势支持 - 支持滑动删除等手势操作
- 无障碍 - 添加适当的 ARIA 标签和键盘导航
📚 相关文档
- Contact 联系人 - 联系人选择组件
- Card 卡片 - 基础卡片组件
- Cell 单元格 - 单元格组件
- ConfigProvider 全局配置 - 了解主题定制方法
🔗 延伸阅读
- 移动端联系人管理最佳实践 - MDN 联系人选择器 API
- 无障碍设计指南 - WCAG 2.1 快速参考
- 移动端触摸交互设计 - Material Design 手势指南
- Vue 3 组合式 API - Vue 3 官方文档