Vant 从 v2 升级到 v3 完全迁移指南:v-model、组件命名与 API 变更全解析
2026/9/12 17:25:39 网站建设 项目流程

Vant 从 v2 升级到 v3 完全迁移指南:v-model、组件命名与 API 变更全解析

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

Vant 3 是基于 Vue 3 重写的移动端组件库,从 Vant 2 升级并非简单的版本号替换,而是涉及组件命名、v-model 用法、全局方法注册方式等多方面的破坏性变更。本文以 Vant 官方迁移文档为骨架,结合 vant 组件库源码 逐一剖析每一项不兼容更新背后的设计原因与迁移写法,帮助你在升级 Vue 3 的同时,以最小代价完成 Vant 2 到 Vant 3 的平滑过渡。

升级前的准备:两步走策略

官方迁移文档给出的升级路径非常清晰,共两步:

  1. 升级 Vue 3:Vant 3 基于 Vue 3 开发,使用前必须将项目中的 Vue 升级到 3.0 以上版本,这是所有后续工作的前提。
  2. 处理不兼容更新:Vant 2 到 Vant 3 存在一批破坏性变更,需要对照下文逐一处理。

迁移的难点集中在第二步。Vant 3 全面拥抱 Vue 3 的新特性(如Teleport、多参数v-model、组合式 API),因此几乎所有变更都源于对 Vue 3 新语法范式的适配。下文按「组件结构 → v-model 体系 → 属性命名 → 逐组件 API → 全局方法」的顺序展开。

组件命名调整:GoodsAction 重命名为 ActionBar

Vant 2 中的「商品导航」组件GoodsAction在 Vant 3 中更名为ActionBar(行动栏),子组件同步从GoodsActionIconGoodsActionButton更名为ActionBarIconActionBarButton

<!-- Vant 2 --> <van-goods-action> <van-goods-action-icon text="图标" /> <van-goods-action-button text="按钮" /> </van-goods-action> <!-- Vant 3 --> <van-action-bar> <van-action-bar-icon text="图标" /> <van-action-bar-button text="按钮" /> </van-action-bar>

从源码看,ActionBar.tsx 通过createNamespace('action-bar')声明了van-action-bar前缀,并通过useChildren(ACTION_BAR_KEY)ActionBarIconActionBarButton建立父子通信,因此三个标签必须整体同步替换,混用新旧前缀会导致子组件无法正确关联父组件状态。同时,badge徽标属性同样作用于ActionBarIcon(下文详述)。

废弃组件:SwitchCell 由 Cell + Switch 组合替代

Vant 2 的SwitchCell(开关单元格)在 Vant 3 中被移除,官方推荐直接使用CellSwitch组合实现相同效果:

<!-- Vant 2 --> <van-switch-cell title="标题" v-model="checked" /> <!-- Vant 3 --> <van-cell center title="标题"> <template #right-icon> <van-switch v-model="checked" size="24" /> </template> </van-cell>

迁移要点:

  • 通过Cell#right-icon插槽将Switch放到单元格右侧,用center属性实现垂直居中;
  • 此时SwitchCell是两个独立组件,不再共享开关状态逻辑,v-model直接绑定在Switch上即可;
  • 若希望点击整行切换开关,需要自行在Cell上绑定@click并同步翻转状态——这正是 Vant 3 组件更「原子化」的设计取向。

v-model 体系全面重构(Vue 3 语法适配)

Vue 3 将v-model升级为多参数模型(v-model:xxx)并统一了 prop/event 命名,Vant 3 的 v-model 变更可以分为三类,逐一对照迁移。

1. 弹窗型组件:v-model 重命名为 v-model:show

以下弹窗类组件的v-model全部重命名为v-model:show

  • ActionSheet
  • Calendar
  • Dialog
  • ImagePreview
  • Notify
  • Popover
  • Popup
  • ShareSheet
<!-- Vant 2 --> <van-popup v-model="show" /> <!-- Vant 3 --> <van-popup v-model:show="show" />

以 Popup.tsx 为例,组件内部通过emit('update:show', true)驱动显隐状态,这正是 Vue 3 命名规范中v-model:show对应的底层事件契约——v-model:show="show"等价于:show="show" @update:show="show = $event"

2. 表单型组件:prop 重命名为 modelValue

以下表单型组件将v-model对应的 prop 重命名为modelValue,事件重命名为update:modelValue

  • Checkbox
  • CheckboxGroup
  • DatetimePicker
  • DropdownItem
  • Field
  • Radio
  • RadioGroup
  • Search
  • Stepper
  • Switch
  • Sidebar
  • Uploader
<!-- Vant 2 --> <van-field :value="value" @input="onInput" /> <!-- Vant 3 --> <van-field :model-value="value" @update:model-value="onInput" />

注意事件名在模板中需写作 kebab-case 的@update:model-value。Vue 3 的v-model语法糖本身就会展开为modelValue+update:modelValue,因此这些组件在模板中继续写v-model通常无需改动;需要改的是那些曾经手动绑定:value/@input的写法

3. 其他 v-model 专项调整

部分组件拥有多个可绑定状态,在 Vant 3 中通过具名v-model:xxx显式表达:

组件Vant 2Vant 3
Circlev-modelv-model:currentRate
CouponListv-modelv-model:code
Listv-modelv-model:loading
Listerror.syncv-model:error
Tabsv-modelv-model:active
TreeSelectactive-id.syncv-model:active-id
TreeSelectmain-active-index.syncv-model:main-active-index

这里体现了 Vue 3 的另一个重要变化:.sync修饰符已被移除,其功能由具名v-model完全取代。例如 Tabs 在 Tabs.tsx 中通过emit('update:active', newName)同步当前激活项,对应模板写法就是v-model:active

<!-- Vant 3 --> <van-tabs v-model:active="active"> <van-tab title="标签 1" /> <van-tab title="标签 2" /> </van-tabs>

徽标属性重命名:info 改为 badge

Vant 2 使用info属性展示图标右上角的数字徽标,Vant 3 为贴合社区命名习惯统一重命名为badge,影响以下组件:

  • Tab
  • Icon
  • GridItem
  • TreeSelect
  • TabbarItem
  • SidebarItem
  • GoodsActionIcon(即现 ActionBarIcon)

同时,内部封装的 Info 组件也更名为 Badge(对应 badge 组件目录)。

<!-- Vant 2 --> <van-icon info="5" /> <!-- Vant 3 --> <van-icon badge="5" />

使用文本v-model:value绑定徽标数字的场景,只需全局将info替换为badge即可,徽标数值、角标样式等行为保持一致。

挂载属性重命名:get-container 改为 teleport

Vue 3 原生引入了Teleport组件,用于将子内容渲染到任意 DOM 节点。Vant 2 通过get-container属性提供类似能力,Vant 3 为与官方 API 对齐,将该属性重命名为teleport

<!-- Vant 2 --> <template> <van-popup get-container="body" /> <van-popup :get-container="getContainer" /> </template> <script> export default { methods: { getContainer() { return document.querySelector('#container'); }, }, }; </script> <!-- Vant 3 --> <template> <van-popup teleport="body" /> <van-popup :teleport="container" /> </template> <script> export default { beforeCreate() { this.container = document.querySelector('#container'); }, }; </script>

迁移时注意两点:

  • 字符串选择器用法基本不变(如teleport="body"teleport="#app");
  • 函数返回节点的方式需要调整:Vant 2 中get-container接受函数并每次调用求值,Vant 3 直接透传 Vue 3Teleportto属性(string | Element),因此应像示例那样在beforeCreate中把 DOM 引用存为实例属性再传入。

从 Popup.tsx 的渲染逻辑可以看到,teleport存在时组件直接包裹<Teleport to={props.teleport}>渲染遮罩层与过渡层,且当被 teleport 的弹窗在KeepAlive场景下失活时会自动关闭、重新激活时恢复打开。其他弹窗类组件(如 Toast 函数调用 中teleport: 'body'默认值)同样遵循该属性约定。

逐组件 API 调整清单

除上述全局性变更外,官方文档还列出以下组件级 API 调整,迁移时务必逐条核对:

Area / DatetimePicker / Picker

change事件回调不再传入组件实例。Vant 2 中change会附带组件实例便于调用内部方法,Vant 3 出于组合式 API 设计与类型收窄的考虑将其移除,事件回调只携带业务数据。若旧代码依赖实例方法(如picker.getValues()),请改用组件实例上的ref调用(Vant 3 通过expose暴露方法),或在confirm等事件中直接消费返回的数据。

Button

  • 蓝色按钮对应的typeinfo调整为primary
  • 绿色按钮对应的typeprimary调整为success
  • native-type默认值由submit调整为button

第三点在 Button.tsx 的源码中可直接验证:nativeType: makeStringProp<ButtonNativeType>('button')。这意味着 Vant 3 中不显式声明native-type的按钮不会触发表单提交,行为更符合组件库的常规预期;若你的表单依赖按钮默认提交,需显式加上native-type="submit"

Checkbox

Cell内部使用Checkbox时,现在需要手动添加@click.stop阻止事件冒泡,避免点击复选框时同时触发单元格的点击事件。

Dialog

  • allow-html属性默认关闭:Vant 3 出于安全考虑,默认将 message 作为纯文本渲染。源码中 Dialog.tsx 通过allowHtml && typeof content === 'string'决定使用innerHTML还是textContent;确需富文本时显式开启:allow-html="true"
  • before-close用法调整:不再传入done函数,改为通过返回值(或返回 Promise 的解析值)控制关闭。底层由 interceptor.ts 的callInterceptor统一实现:返回true(或 Promise resolve 为真值)执行关闭,返回false(或 resolve 为假值)取消关闭,Promise reject 走 error 分支。典型写法:
const beforeClose = (action) => new Promise((resolve) => { // 异步校验通过后 resolve(true) 允许关闭 setTimeout(() => resolve(true), 1000); });

ImagePreview

移除async-close属性,改用新增的before-close属性实现异步关闭控制,语义与 Dialog 的before-close保持一致。

Picker

  • allow-html属性默认关闭(与 Dialog 同一安全策略);
  • show-toolbar默认开启:源码 Picker.tsx 使用showToolbar: truthProp声明,truthProp即默认值为true的布尔属性;
  • 级联选择(cascader)场景下,confirmchange事件回调参数将包含完整的选项对象,而非仅返回索引或文本,取值方式需相应调整。

Popover

trigger属性的默认值调整为click(Vant 2 为manual),未显式指定触发方式时,点击即弹出。

Stepper

async-change属性重命名为before-change,且使用方法调整:同样改为返回值/Promise 控制步进是否生效,写法与 Dialog 的before-close一致。

SwipeCell

  • open事件的detail参数重命名为name
  • on-close属性重命名为before-close,参数结构同步调整;
  • before-close回调不再传入组件实例。

Toast

mask属性重命名为overlay,与 Vant 3 全局统一命名一致(如 Popup 的overlayoverlay-classoverlay-style体系)。函数式调用场景下,function-call.tsx 的默认配置同样使用overlay: false字段。

TreeSelect

  • navclick事件重命名为click-nav(点击左侧导航栏);
  • itemclick事件重命名为click-item(点击右侧选项项)。

全局方法:必须先 app.use 注册

Vant 2 默认提供$toast$dialog等挂载在 Vue 原型上的全局方法。Vue 3 不再支持在原型链上直接挂载,因此从 Vant 3 起,使用全局方法前必须先将对应组件通过app.use注册到当前 app 实例:

import { Toast, Dialog, Notify } from 'vant'; // 将 Toast 等组件注册到 app 上 app.use(Toast); app.use(Dialog); app.use(Notify); // app 内的子组件可以直接调用 $toast 等方法 export default { mounted() { this.$toast('提示文案'); }, };

该机制在源码中体现为:ToastDialogNotify等组件在install时向 app 提供全局属性(如app.config.globalProperties.$toast),并同时提供可独立导入的函数式 API(如showToastshowDialogshowNotify)。值得注意的是,函数式 API 不依赖组件注册,showToast 通过mountComponent动态挂载实例即可使用;而$toast这类实例方法必须完成注册后才能调用,且注册对象是当前 app 而非全局,即「哪个 app 注册了,哪个 app 的子树内才能用」。

迁移自检清单

完成上述变更后,建议按以下清单逐项自查,避免遗漏:

  • Vue 升级到 3.0+,且引入方式、createApp挂载流程已切换为 Vue 3 写法;
  • 全局搜索van-goods-actionvan-goods-action-iconvan-goods-action-button,替换为van-action-bar系列;
  • 全局搜索van-switch-cell,改为Cell+Switch组合;
  • 弹窗类组件(ActionSheet、Calendar、Dialog、ImagePreview、Notify、Popover、Popup、ShareSheet)的v-model改为v-model:show
  • 表单类组件中手动绑定的:value/@input改为:model-value/@update:model-value
  • 处理.sync修饰符,统一改写为具名v-model:xxx
  • info徽标属性全局替换为badge
  • get-container全局替换为teleport,并调整函数式传参写法;
  • 按上文 API 调整清单核对 Button、Dialog、Picker、Stepper、SwipeCell、Toast、TreeSelect 等组件的属性与事件;
  • 确认$toast$dialog$notify等全局方法已通过app.use注册,或改用函数式 API(showToast等)。

迁移完成后建议重点回归验证三类场景:弹窗的显隐控制与异步关闭、表单的双向绑定、Picker 等选择器的回调参数取值。Vant 3 的其余新特性(如主题定制、按需引入方式)不受本次迁移影响,可参照仓库内各组件的 README.zh-CN.md 逐步探索。

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询