Wot UI v1 升级 v2?这份迁移指南帮你少踩坑!

大家好,我是不如摸鱼去,wot-ui 的主要维护者,欢迎来到我的 uni-app 分享专栏。

Wot UI v2 发布后,不少朋友私信问我怎么从 v1 升级上来。说实话,这次改动确实不小,不只是换个包名那么简单------表单校验体系、主题变量、组件命名、工程配置都有调整。

这篇文章会把迁移过程中需要关注的点都梳理一遍,帮你少走弯路。

建议按顺序来:先搞定依赖和路径替换,再处理 Form、Dialog、Cascader 这些变动大的组件,最后做样式和平台回归。

我们同时也提供了迁移的 skills,你可以这样安装:

sql 复制代码
pnpx skills add wot-ui/open-wot
# or
npx skills add wot-ui/open-wot

迁移概览

先看一张表,心里有个数:

类型 v1 v2
npm 包名 wot-design-uni @wot-ui/ui
uni_modules 目录 wot-design-uni wot-ui
组合式函数导入 @/uni_modules/wot-design-uni @/uni_modules/wot-ui
弹框组件 wd-message-box wd-dialog
弹框 Hook useMessage useDialog
缺省提示 wd-status-tip wd-empty
多列选择器 wd-col-picker wd-cascader
表单校验 rules / FormRules schema / FormSchema
按钮变体 plain / type="text" / type="icon" variant / 图标按钮
标签变体 plain variant="plain"
单选 / 复选形态 shape / inline / cell type / direction / 手动组合 wd-cell
搜索框浅色样式 light variant="light"
GridItem 点击事件 itemclick click
工具函数路径 components/common/util common/util
主题系统 CSS 变量覆盖 Design Token 三层变量体系
Sass 建议锁定较低版本 推荐 1.98 及以上版本

::: warning 注意 v2 的组件命名、包名和部分 API 跟 v1 不完全兼容。别光升级依赖版本就完事了,按本文顺序逐项检查才稳当。 :::

升级前检查

动手之前,先在项目里搜一下旧包名和旧组件,看看影响面有多大:

bash 复制代码
rg "wot-design-uni|wd-message-box|useMessage|wd-status-tip|wd-col-picker|wd-number-keyboard|@itemclick|shape=|inline|\\scell\\b|\\slight\\b|type=\"error\"|type=\"icon\"|type=\"text\"|\\splain\\b|classPrefix|components/common/util|hide-label|hide-min-max|autoLineWidth|disabled-color|setRoate|useContentSlot|useMoreSlot|\\bshow="

项目里有表单页面的话,再跑一下这条:

bash 复制代码
rg "wd-form|FormRules|:rules=|rules=|errorType|resetOnChange"

重点确认这几件事:

  • 项目用 npm 安装还是 uni_modules 安装。
  • pages.json 里有没有配 easycom。
  • tsconfig.json 里有没有配全局组件类型。
  • 有没有用到 MessageBox、StatusTip、ColPicker、NumberKeyboard。
  • Button 有没有用 plain、type="error"、type="text"、type="icon"。
  • Tag 有没有用 plain。
  • Radio / Checkbox 有没有用 shape、inline、cell、icon-placement。
  • Search 有没有用 light。
  • 有没有监听 wd-grid-item 的 itemclick 事件。
  • 有没有调用 PickerView、ImgCropper、CountTo 等组件实例方法。
  • Badge、Slider、Tabs、Rate、SlideVerify、Steps、Swiper 这些组件有没有用旧属性。
  • Tooltip、Popover、Collapse 有没有用旧的显隐属性或旧插槽开关。
  • 有没有复杂表单、动态表单、隐藏字段校验或自定义校验规则。
  • 有没有覆盖过组件内部样式或自定义过主题变量。

安装迁移

npm 安装

把旧包卸掉,装新的:

::: code-group

bash 复制代码
npm remove wot-design-uni
npm i @wot-ui/ui
bash 复制代码
yarn remove wot-design-uni
yarn add @wot-ui/ui
bash 复制代码
pnpm remove wot-design-uni
pnpm add @wot-ui/ui

:::

导入路径也要跟着改:

ts 复制代码
// v1
import { useToast } from 'wot-design-uni'

// v2
import { useToast } from '@wot-ui/ui'

uni_modules 安装

用 uni_modules 的话,把插件目录从 wot-design-uni 改成 wot-ui

bash 复制代码
uni_modules
└── wot-ui

导入路径同步替换:

ts 复制代码
// v1
import { useToast } from '@/uni_modules/wot-design-uni'

// v2
import { useToast } from '@/uni_modules/wot-ui'

Sass 迁移

v2 推荐用 sass@^1.98.0

::: code-group

bash 复制代码
npm i sass@^1.98.0 -D
bash 复制代码
yarn add sass@^1.98.0 -D
bash 复制代码
pnpm add sass@^1.98.0 -D

:::

升完 sass,项目里原有的业务样式也可能要跟着调。新版 Sass 对旧语法和旧 API 的兼容提示更严格,如果你项目里有比较早期的 Sass 写法,编译时可能会出警告或错误。

重点检查这几项:

  • 有没有还在用 @import 引入 Sass 文件,必要时改成 @use@forward
  • 有没有依赖全局可见的变量、mixin 或 function。迁移到 @use 后,要通过命名空间访问,或者用 as * 显式展开。
  • 有没有用旧的除法写法 /。如果用于数学计算,建议改成 math.div()
  • 有没有调 Sass 废弃的内置函数或旧 API。
  • 有没有第三方样式库锁定了较旧的 Sass 语法,需要同步升级对应依赖。

举个例子:

scss 复制代码
// 旧写法
@import './variables.scss';

.page {
  width: 100px / 2;
  color: $primary-color;
}

可以逐步改成:

scss 复制代码
@use 'sass:math';
@use './variables.scss' as *;

.page {
  width: math.div(100px, 2);
  color: $primary-color;
}

如果遇到 legacy JS API 相关警告,可以在 vite.config.ts 里加配置:

ts 复制代码
export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        api: 'modern-compiler',
        silenceDeprecations: ['legacy-js-api']
      }
    }
  }
})

自动导入迁移

easycom

用 npm 安装,通过 easycom 自动引入组件的,路径要改成新包名:

json 复制代码
{
  "easycom": {
    "autoscan": true,
    "custom": {
      "^wd-(.*)": "@wot-ui/ui/components/wd-$1/wd-$1.vue"
    }
  }
}

用 uni_modules 安装的话,一般不需要额外配置。如果之前手动写过旧目录路径,也要替换成 @/uni_modules/wot-ui

vite 插件自动导入

通过 @uni-helper/vite-plugin-uni-components 自动导入组件的,可以用项目内自定义 resolver:

ts 复制代码
import type { ComponentResolver } from '@uni-helper/vite-plugin-uni-components'
import { kebabCase } from '@uni-helper/vite-plugin-uni-components'

export function WotResolver(): ComponentResolver {
  return {
    type: 'component',
    resolve: (name: string) => {
      if (name.match(/^Wd[A-Z]/)) {
        const compName = kebabCase(name)
        return {
          name,
          from: `@wot-ui/ui/components/${compName}/${compName}.vue`
        }
      }
    }
  }
}

Volar 类型

npm 安装时,tsconfig.json 里的类型声明要替换:

json 复制代码
{
  "compilerOptions": {
    "types": ["@wot-ui/ui/global"]
  }
}

Form 表单迁移

Form 是 v2 里变化最大的组件之一。v1 更偏向「表单组件直接承载校验规则」,v2 统一成了 wd-formwd-form-itemschema 校验模型。

基础结构迁移

v1 里,输入组件通常直接放在 wd-form 内,组件上声明 proprules

vue 复制代码
<wd-form ref="form" :model="model" :rules="rules">
  <wd-input
    label="用户名"
    prop="username"
    v-model="model.username"
    :rules="[{ required: true, message: '请填写用户名' }]"
  />
</wd-form>

v2 推荐用 wd-form-item 承载标题、布局、校验提示和点击行为,输入组件只管输入:

vue 复制代码
<wd-form ref="form" :model="model" :schema="schema" :title-width="100">
  <wd-form-item title="用户名" prop="username">
    <wd-input v-model="model.username" placeholder="请填写用户名" />
  </wd-form-item>
</wd-form>

::: tip 提醒 wd-form-iteminputtextarea 结合用时,会自动开启 compact 属性。迁移后如果表单项高度或间距变了,先检查这里。 :::

校验规则迁移

v1 用 rules

ts 复制代码
import type { FormRules } from '@/uni_modules/wot-design-uni/components/wd-form/types'

const rules: FormRules = {
  username: [
    {
      required: true,
      message: '请填写用户名'
    }
  ]
}

v2 用 schema。想要更好的类型推导,推荐用 zodAdapter

ts 复制代码
import { z } from 'zod'
import { zodAdapter } from '@/uni_modules/wot-ui'

const schema = zodAdapter(
  z.object({
    username: z.string().min(1, '请填写用户名')
  })
)

用 npm 安装时,导入路径改成:

ts 复制代码
import { zodAdapter } from '@wot-ui/ui'

Zod 不会随组件库内置安装,需要自己装:

::: code-group

bash 复制代码
npm i zod
bash 复制代码
yarn add zod
bash 复制代码
pnpm add zod

:::

不想引 Zod 的话,也可以手写 FormSchema

ts 复制代码
import type { FormSchema } from '@/uni_modules/wot-ui/components/wd-form/types'

const schema: FormSchema = {
  validate(model) {
    const issues = []
    if (!model.username) {
      issues.push({ path: ['username'], message: '请填写用户名' })
    }
    return issues
  },
  isRequired(path: string) {
    return path === 'username'
  }
}

必填星号迁移

v2 里,必填星号和校验规则是两回事。控制星号有几种方式:

  • wd-form-item 上设 required
  • FormSchema 里提供 isRequired(path)
  • zodAdapter 的第二个参数里提供 isRequired(path)
ts 复制代码
const schema = zodAdapter(
  z.object({
    username: z.string().min(1, '请填写用户名')
  }),
  {
    isRequired(path: string) {
      return path === 'username'
    }
  }
)

迁移后校验正常但星号没显示的话,先检查 requiredisRequired

选择器表单项迁移

v1 里,Input、Textarea、Picker、Calendar、DatetimePicker、SelectPicker、ColPicker 这些组件经常直接当表单项用,组件自身支持 labellabel-widthproprules 等属性:

vue 复制代码
<wd-col-picker
  label="地址"
  prop="address"
  v-model="model.address"
  :columns="area"
/>

v2 里,表单结构统一收到 wd-form-item。输入组件和弹层选择器不再承担表单标题、校验展示和触发入口的职责,迁移时要把 labellabel-widthproprules 等配置挪到 wd-formwd-form-itemschema 上。

弹层选择器建议拆开:选择器管选择,wd-form-item 管展示当前值、打开弹层和显示校验状态。

vue 复制代码
<wd-cascader
  v-model="model.address"
  v-model:visible="showAddressPicker"
  :options="area"
  @confirm="handleAddressConfirm"
/>

<wd-form-item
  title="地址"
  prop="address"
  is-link
  :value="addressText"
  placeholder="请选择地址"
  @click="showAddressPicker = true"
/>
ts 复制代码
import type { CascaderOption } from '@/uni_modules/wot-ui/components/wd-cascader/types'

const showAddressPicker = ref(false)
const addressText = ref('')

function handleAddressConfirm({ selectedOptions }: { selectedOptions: CascaderOption[] }) {
  addressText.value = selectedOptions.map((item) => item.text).join('/')
}

::: tip 提醒 选择类组件迁移后,检查一下 model 里存的是组件值还是展示文本。wd-form-itemvalue 通常用于展示,不一定等于提交给后端的字段值。 :::

布局属性迁移

v2 的 Form 和 FormItem 布局能力更强了,原来散落在各输入组件上的布局配置,可以优先上移到 wd-formwd-form-item

vue 复制代码
<wd-form
  :model="model"
  :schema="schema"
  :title-width="100"
  layout="horizontal"
  value-align="left"
  border
  asterisk-position="end"
>
  <wd-form-item title="用户名" prop="username">
    <wd-input v-model="model.username" />
  </wd-form-item>
</wd-form>

常用布局属性:

属性 说明
border 是否展示边框线
center 是否使内容垂直居中
size 单元格大小
title-width 左侧标题宽度
layout 表单项布局,可选 horizontalvertical
value-align 右侧内容对齐方式
asterisk-position 必填星号位置
hide-asterisk 是否隐藏必填星号
ellipsis 是否超出隐藏显示省略号

校验触发迁移

v2 支持通过 validate-trigger 控制校验触发时机:

vue 复制代码
<wd-form :model="model" :schema="schema" validate-trigger="change">
  <wd-form-item title="用户名" prop="username" validate-trigger="blur">
    <wd-input v-model="model.username" />
  </wd-form-item>
</wd-form>

validate 方法照样支持校验全部字段、单个字段或多个字段:

ts 复制代码
await form.value?.validate()
await form.value?.validate('username')
await form.value?.validate(['username', 'password'])

Form 迁移清单

  • 把挂在输入组件上的 proprules 迁移到 wd-form-itemschema
  • rules / FormRules / FormItemRule 替换成 schema / FormSchema
  • 用 Zod 的话,装上 zod,通过 zodAdapter 转换校验规则。
  • 检查必填星号是否需要通过 requiredisRequired 单独控制。
  • errorType 改成 error-typeresetOnChange 改成 reset-on-change
  • ColPicker 场景迁移到 Cascader,确认回显文本和提交值。
  • 检查动态字段、隐藏字段、数组字段和异步校验。
  • 检查 validate()validate(prop)reset() 的调用是否还符合业务预期。

组件迁移

模板属性命名

v2 文档里的模板示例统一用 kebab-case 属性名。迁移时建议把模板里的 camelCase 写法也调整一下,尤其是直接从旧文档复制过来的代码。

vue 复制代码
<!-- v1 中常见写法 -->
<wd-toast :zIndex="1000" classPrefix="custom" />
<wd-count-to :startVal="0" :endVal="100" />

<!-- v2 推荐写法 -->
<wd-toast :z-index="1000" class-prefix="custom" />
<wd-count-to :start-val="0" :end-val="100" />

常见属性包括 z-indexclass-prefixcustom-classcustom-stylesafe-area-inset-bottomstart-valend-valauto-startuse-easing 等。

MessageBox 迁移为 Dialog

v1:

vue 复制代码
<wd-message-box />
ts 复制代码
import { useMessage } from '@/uni_modules/wot-design-uni'

const message = useMessage()
message.confirm({
  title: '提示',
  msg: '确认删除?'
})

v2:

vue 复制代码
<wd-dialog />
ts 复制代码
import { useDialog } from '@/uni_modules/wot-ui'

const dialog = useDialog()
dialog.confirm({
  title: '提示',
  msg: '确认删除?'
})

页面里有多个弹框实例的话,继续用 selector 区分:

vue 复制代码
<wd-dialog selector="delete-dialog" />
ts 复制代码
const dialog = useDialog('delete-dialog')

Dialog 跟 MessageBox 还有几个行为差异要注意:

  • closeOnClickModal 默认值从 true 改成了 false,想点遮罩关闭的话要显式设置。
  • Prompt 的返回值是 DialogResult,读输入内容用 res.value
  • inputTypeinputPlaceholder 等扁平配置推荐迁移到 inputProps;多行输入用 textareaProps
  • 确认、取消按钮的高级配置用 confirmButtonPropscancelButtonProps,多按钮场景用 actions
ts 复制代码
dialog.prompt({
  title: '请输入手机号',
  inputProps: {
    type: 'tel',
    placeholder: '请输入 11 位手机号'
  }
}).then((res) => {
  console.log(res.value)
})

Button 迁移

v2 对按钮类型和变体做了拆分,迁移时重点检查 typeplainround 和图标按钮。

v1 v2
type="error" type="danger"
plain variant="plain"
type="text" variant="text"
type="icon" icon="xxx" 只传 icon="xxx"
classPrefix 模板中推荐写作 class-prefix
vue 复制代码
<!-- v1 -->
<wd-button type="error" plain>删除</wd-button>
<wd-button type="text">文字按钮</wd-button>
<wd-button type="icon" icon="picture" />
vue 复制代码
<!-- v2 -->
<wd-button type="danger" variant="plain">删除</wd-button>
<wd-button variant="text">文字按钮</wd-button>
<wd-button icon="image" />

::: tip 提醒 v2 里 Button 的 round 默认值是 false,按钮高度也改成固定高度控制了。如果项目依赖 v1 的圆角外观或通过内边距撑开的高度,要做视觉回归。 :::

Tag 迁移

v2 的 Tag 用 variant 表达视觉变体,plain 要改成 variant="plain"

vue 复制代码
<!-- v1 -->
<wd-tag plain>标签</wd-tag>
<wd-tag mark plain>标签</wd-tag>
vue 复制代码
<!-- v2 -->
<wd-tag variant="plain">标签</wd-tag>
<wd-tag mark variant="plain">标签</wd-tag>

如果在数据里维护标签配置,也要同步调:

ts 复制代码
// v1
const tag = { type: 'primary', plain: true }

// v2
const tag = { type: 'primary', variant: 'plain' }

Radio 和 Checkbox 迁移

v2 对 Radio、Checkbox 的形态、排列和列表模式做了统一,旧的 shapeinlinecell 要迁移。

v1 v2
shape="check" type="circle"
shape="dot" type="dot"
shape="button" type="button"
shape="square" type="square"
inline direction="horizontal"
icon-placement="left/right" placement="left/right"
cell 手动组合 wd-cell
vue 复制代码
<!-- v1 -->
<wd-radio-group v-model="value" shape="button" inline>
  <wd-radio :value="1">选项一</wd-radio>
  <wd-radio :value="2">选项二</wd-radio>
</wd-radio-group>

<!-- v2 -->
<wd-radio-group v-model="value" type="button" direction="horizontal">
  <wd-radio :value="1">选项一</wd-radio>
  <wd-radio :value="2">选项二</wd-radio>
</wd-radio-group>

v1 的 cell 模式在 v2 里不再作为 RadioGroup / CheckboxGroup 的内置属性了。需要整行点击时,把选项放进 wd-cell,在 wd-cell 的点击事件里更新值或调用组件实例方法。

vue 复制代码
<wd-radio-group v-model="value">
  <wd-cell-group border>
    <wd-cell title="选项一" clickable @click="value = 1">
      <template #right-icon>
        <wd-radio :value="1" />
      </template>
    </wd-cell>
  </wd-cell-group>
</wd-radio-group>

Checkbox 迁移还要注意:CheckboxGroup 里选项值用 name 表达,单独用 wd-checkbox 时才用 v-modeltrue-valuefalse-value 管理选中和未选中值。

v1 的 light 布尔属性在 v2 里改成 variant="light"

vue 复制代码
<!-- v1 -->
<wd-search light />

<!-- v2 -->
<wd-search variant="light" />

用了右侧输入框插槽的话,v2 推荐直接用 input-suffixsuffix 等具名插槽,不再通过已废弃的 use-suffix-slot 控制。

Cell、Input 和 Textarea 迁移

v1 里 Cell、Input、Textarea 曾经承担一部分表单项职责,常见属性包括 propruleslabellabel-widthrequiredmarker-sideno-border 等。v2 里这些职责要迁移到 wd-form-itemwd-formschema

vue 复制代码
<!-- v1 -->
<wd-input label="用户名" prop="username" v-model="model.username" required />

<!-- v2 -->
<wd-form-item title="用户名" prop="username" required>
  <wd-input v-model="model.username" />
</wd-form-item>

Cell 自身的图标和布局属性也有调整:

v1 v2
icon prefix-icon
custom-icon-class custom-prefix-classcustom-suffix-class
vertical layout="vertical"
marker-side asterisk-position

Input、Textarea 放进 wd-cellwd-form-item 时,建议用 compact 移除组件自身的内边距和背景;在 wd-form-item 里会自动开启。

Fab 迁移

Fab 的主题类型跟 Button 保持一致,旧的 type="error" 要改成 type="danger"

vue 复制代码
<!-- v1 -->
<wd-fab type="error" :zIndex="99" inactiveIcon="plus" activeIcon="close" />

<!-- v2 -->
<wd-fab type="danger" :z-index="99" inactive-icon="plus" active-icon="close" />

Fab 插槽里的按钮如果还在用 type="error",也要同步改成 type="danger"

Grid 迁移

wd-grid-item 的点击事件从 itemclick 改成 click

vue 复制代码
<!-- v1 -->
<wd-grid clickable>
  <wd-grid-item text="开始" icon="play-circle-stroke" @itemclick="start" />
</wd-grid>
vue 复制代码
<!-- v2 -->
<wd-grid clickable>
  <wd-grid-item text="开始" icon="play-circle-stroke" @click="start" />
</wd-grid>

::: tip 提醒 wd-grid-item 要配合父级 wd-gridclickable 用,没开启 clickable 时不会触发点击逻辑。 :::

StatusTip 迁移为 Empty

v2 用 wd-empty 表达空状态、网络异常、无结果等场景:

vue 复制代码
<wd-empty icon="no-result" tip="当前搜索无结果" />
<wd-empty icon="no-wifi" tip="当前网络不可用,请检查你的网络设置" />
<wd-empty icon="no-content" tip="暂无内容" />

v1 里用了自定义图片或底部操作区的,可以迁移到 wd-empty 的插槽:

vue 复制代码
<wd-empty icon="no-content" tip="暂无内容">
  <wd-button type="primary">重新加载</wd-button>
</wd-empty>

ColPicker 迁移为 Cascader

v2 用 wd-cascader 替代 wd-col-picker。迁移时重点检查数据结构、异步加载和回显逻辑。

vue 复制代码
<wd-cascader
  v-model="model.address"
  v-model:visible="showAddressPicker"
  :options="area"
  @confirm="handleAddressConfirm"
/>

Cascader 的选项支持通过 value-keytext-keychildren-key 等属性适配自定义字段。迁移 ColPicker 的 column-change 逻辑时,可以改用 lazy-load

Picker、Calendar 和 DatetimePicker 触发方式

v2 里,Picker、SelectPicker、Calendar、DatetimePicker 等弹层选择器更偏向纯选择器职责,不再把外层触发单元格当主要结构。旧代码里如果直接依赖这些组件的 labellabel-widthproprules 等表单项能力,建议改成 wd-cellwd-form-item 负责触发和展示。

vue 复制代码
<wd-picker v-model="model.type" v-model:visible="showTypePicker" :columns="typeList" />

<wd-form-item
  title="类型"
  prop="type"
  is-link
  :value="typeText"
  placeholder="请选择类型"
  @click="showTypePicker = true"
/>

CountTo 迁移

v2 里 CountTo 的主题类型是 defaultprimarysuccesswarningerror。旧代码用了 type="info" 的话,要换成其他主题或通过 color 自定义颜色。

vue 复制代码
<!-- v1 -->
<wd-count-to type="info" :startVal="0" :endVal="888888" :autoplay="false" fontSize="24px" />

<!-- v2 -->
<wd-count-to type="primary" :start-val="0" :end-val="888888" :auto-start="false" custom-style="font-size: 24px;" />

模板里也建议统一用 kebab-case 属性,比如 start-valend-valauto-start。旧代码用 fontSize 控制字号的,v2 可以改成 custom-stylecustom-class 或外层样式控制。

Segmented 迁移

v2 的 Segmented 用 theme 控制样式,不再提供 size。旧代码用了 size="large"size="small" 的话,要按设计稿通过外层样式、custom-class 或组件变量调整尺寸。

vue 复制代码
<!-- v1 -->
<wd-segmented :options="list" v-model:value="current" size="large" />

<!-- v2 -->
<wd-segmented :options="list" v-model:value="current" theme="card" />

模板里 vibrateShort 建议改成 vibrate-short

PickerView 迁移

PickerView 的级联模型变化比较大。v1 常通过 column-change 和实例方法 setColumnData 动态修改列数据,v2 推荐用 cascade 和树形 columns 数据。

vue 复制代码
<!-- v2 -->
<wd-picker-view v-model="value" :columns="columns" cascade />

实例方法也有命名调整:

v1 v2
getLabels() getSelectedLabels()
setColumnData() cascade 树形数据,或通过 resetColumns() 重置列数据
getColumnData() getColumnData() 保留
resetColumns() resetColumns() 保留

v2 的 v-model 推荐始终用数组形式保存选中值,单列选择也建议写成 ['value']

ImgCropper 迁移

项目里通过组件实例调用图片裁剪方法的,要把拼写错误的 setRoate 改成 setRotate

ts 复制代码
// v1
cropper.value?.setRoate(90)

// v2
cropper.value?.setRotate(90)

更多组件迁移补充

下面这些组件的变化比较分散,但如果项目里用到对应旧属性,也要一起调。

组件 v1 v2
Badge v-model / modelValue value
Slider 数组值自动双滑块 需要显式设置 range
Slider hide-label popover-visible="never" 隐藏气泡
Slider hide-min-max show-extreme-value 控制是否展示极值
Tabs autoLineWidth line-theme="text"
Rate disabled-color 通过 coloractive-color 或自定义样式处理禁用态视觉
SlideVerify width / height 通过外层容器、custom-style 或样式类控制尺寸
Steps title-slot / description-slot / icon-slot 直接用 titledescriptionicon 插槽
Swiper pagination-position indicator-position
DatetimePickerView columns-height item-height / visible-item-count
vue 复制代码
<!-- Badge -->
<wd-badge :value="12" />

<!-- Slider -->
<wd-slider v-model="rangeValue" range show-extreme-value popover-visible="never" />

<!-- Tabs -->
<wd-tabs v-model="tab" line-theme="text" />

DatetimePickerView 的 loadingloading-color 不再作为视图组件属性提供;旧页面依赖加载态的,建议在外层自行控制 loading 展示,再渲染选择器。

Swiper 的指示器能力也做了收口,数字、点状、点条状等样式优先通过 indicator 配置,位置用 indicator-position

vue 复制代码
<wd-swiper
  v-model:current="current"
  :list="list"
  :indicator="{ type: 'fraction' }"
  indicator-position="bottom-right"
/>

Tooltip、Popover 和 Collapse 迁移

Tooltip 的受控显隐从旧的 show 属性收口到 v-model / model-value

vue 复制代码
<!-- v1 -->
<wd-tooltip :show="show" content="提示内容">
  <wd-button>提示</wd-button>
</wd-tooltip>

<!-- v2 -->
<wd-tooltip v-model="show" content="提示内容">
  <wd-button>提示</wd-button>
</wd-tooltip>

Tooltip、Popover 用 content 插槽时,不再需要旧的 useContentSlot 开关。迁移后如果插槽内容尺寸会动态变化,可以通过实例方法 updatePosition() 重新计算定位。

vue 复制代码
<wd-popover v-model="showPopover" ref="popoverRef">
  <template #content>
    <view>自定义内容</view>
  </template>
  <wd-button>打开</wd-button>
</wd-popover>

Collapse 的绑定值从旧的 value 属性迁移到 v-model。用查看更多模式的话,自定义 more 插槽时模板属性推荐写成 use-more-slot

vue 复制代码
<!-- v1 -->
<wd-collapse :value="active" useMoreSlot>
  ...
</wd-collapse>

<!-- v2 -->
<wd-collapse v-model="active" use-more-slot>
  ...
</wd-collapse>

NumberKeyboard

v2 不再提供独立的 wd-number-keyboard。项目里依赖这个组件的话,优先评估迁移到 wd-keyboard

vue 复制代码
<wd-keyboard v-model="value" v-model:visible="visible" mode="custom" extra-key="." close-text="完成" />

车牌号、身份证、随机数字键盘等场景也由 wd-keyboard 承载。迁移时重点检查 visiblev-modelextra-keyclose-textrandom-key-ordersafe-area-inset-bottom 等属性和事件。

新增预览组件

v2 新增了图片和视频预览能力:

项目里原来直接调 uni.previewImage 或维护自定义视频预览层的,可以按需迁移到这些组件。

工具函数和类型导入迁移

项目里直接引用了组件库内部工具函数的,路径要同步调:

ts 复制代码
// v1
import { isArray, getRect, pause } from '@/uni_modules/wot-design-uni/components/common/util'

// v2
import { isArray, getRect, pause } from '@/uni_modules/wot-ui/common/util'

npm 安装时,可以从包内路径导入:

ts 复制代码
import { isArray, getRect, pause } from '@wot-ui/ui/common/util'

也可以从包入口用 CommonUtil 命名空间:

ts 复制代码
import { CommonUtil } from '@wot-ui/ui'

CommonUtil.isArray([])

组件类型导入也要替换包名或目录名:

ts 复制代码
// v1
import type { UploadFileItem } from '@/uni_modules/wot-design-uni/components/wd-upload/types'

// v2
import type { UploadFileItem } from '@/uni_modules/wot-ui/components/wd-upload/types'

图标迁移

v2 对图标示例和部分组件默认图标做了调整。迁移后页面出现空图标、图标名称不匹配或视觉含义不一致的,优先检查 iconprefix-iconsuffix-iconclass-prefixcss-icon 等配置。

常见场景:

  • Button 旧的 type="icon" 要改成直接传 icon
  • 自定义图标类名前缀在模板里推荐用 class-prefix
  • 旧示例里的一些图标名可能要替换成 v2 图标文档里存在的名称。

主题与深色模式迁移

v2 的主题系统基于 Design Token,推荐优先覆盖语义变量,再按需覆盖组件变量。

用深色模式或主题变量的话,需要在入口样式里引入主题文件:

::: code-group

scss 复制代码
@use '@wot-ui/ui/styles/theme/index.scss' as *;
scss 复制代码
@use '@/uni_modules/wot-ui/styles/theme/index.scss' as *;

:::

全局品牌色建议覆盖语义变量:

scss 复制代码
page,
.wd-root-portal {
  --wot-primary-5: #4096ff;
  --wot-primary-6: #1677ff;
  --wot-primary-7: #0958d9;
}

局部主题建议用 ConfigProvider 全局配置

vue 复制代码
<wd-config-provider :theme-vars="themeVars">
  <wd-button type="primary">提交</wd-button>
</wd-config-provider>

更多主题说明参考 定制主题深色模式

样式覆盖迁移

v2 推荐按以下优先级覆盖样式:

  1. 优先用组件提供的 custom-classcustom-style
  2. 需要统一品牌视觉时,优先覆盖 CSS 变量。
  3. 页面内覆盖组件样式时,普通样式可以直接用 .wd-* 类名。
  4. scoped 样式里覆盖组件内部样式时,用 :deep()
  5. 在自定义组件内覆盖小程序组件样式时,检查 styleIsolation: 'shared'
css 复制代码
:deep(.wd-button) {
  font-weight: 600;
}

更多说明参考 样式覆盖

国际化迁移

用 npm 安装,配过 Vite 预构建排除的,要把旧包名替换成新包名:

ts 复制代码
export default defineConfig({
  optimizeDeps: {
    exclude: ['@wot-ui/ui']
  }
})

导入路径同步替换:

ts 复制代码
import { Locale } from '@wot-ui/ui'
import enUS from '@wot-ui/ui/locale/lang/en-US'

uni_modules 安装时:

ts 复制代码
import { Locale } from '@/uni_modules/wot-ui/locale'
import enUS from '@/uni_modules/wot-ui/locale/lang/en-US'

回归测试清单

迁移完成后,至少检查这些内容:

  • H5 和目标小程序端能不能正常编译。
  • easycom 能不能正确解析所有 wd-* 组件。
  • Toast、Dialog、Notify 等函数式调用组件是否已经在页面中声明实例。
  • 表单提交、单字段校验、重置、隐藏字段和异步校验是否正常。
  • 选择器类表单项的回显文本和提交值是否正确。
  • Button 的 typevariantround 和高度是否符合预期。
  • Tag 的 variant 是否已从旧的 plain 迁移。
  • Radio / Checkbox 的 shapeinlinecell 是否已迁移。
  • Search 的 light 是否已迁移为 variant="light"
  • GridItem 点击事件是否已从 itemclick 迁移到 click
  • Cell、Input、Textarea 的表单相关属性是否已迁移到 wd-form-item
  • PickerView、ImgCropper、CountTo 等实例方法是否仍可正常调用。
  • Badge、Slider、Tabs、Steps、Swiper 等旧属性是否已迁移。
  • Dialog 点击遮罩关闭、Prompt 返回值和按钮配置是否符合预期。
  • 深色模式、主题变量、品牌色覆盖是否生效。
  • 弹层、遮罩、Popup、DropMenu、ActionSheet 在小程序端是否存在样式隔离问题。
  • 自定义覆盖样式是否仍然生效。
  • 图标名称是否仍然存在,按钮高度变化是否影响页面布局。

推荐迁移顺序

  1. 升级依赖和 sass。
  2. 替换包名、目录名和导入路径。
  3. 更新 easycom、Volar、国际化配置。
  4. 优先迁移 Form 页面。
  5. 替换 MessageBox、StatusTip、ColPicker、NumberKeyboard 等组件。
  6. 检查 Button、Tag、Radio、Checkbox、Search、GridItem、CountTo、Slider、Tabs 等 API 变化。
  7. 迁移主题变量和样式覆盖。
  8. 在 H5 和目标小程序端做完整回归。

项目里表单页面多的话,建议先挑一个复杂表单完成迁移样板,再批量迁移其他页面。


如果你也在为 v1 升级 v2 而发愁,希望这份指南能帮上忙!有啥问题欢迎在评论区交流。

相关推荐
xiangxiongfly9151 小时前
Vue3 动态加载静态资源
前端·javascript·vue.js
子兮曰1 小时前
whisper.cpp 深度解析:从边缘设备到实时语音识别
前端·c++·后端
子兮曰1 小时前
Ruflo 深度解析:49K Stars 的 AI Agent 编排平台 — 给 Claude Code 装上分布式神经系统
前端·后端·ai编程
小皮咖1 小时前
发给那个让你加班的同事
前端
克里斯蒂亚诺更新1 小时前
ruoyi切换新版本初始化需要修改的地方
前端·javascript·vue.js
可视之道1 小时前
基于Meta2d.js的电力系统组态平台实战开发
前端
小村儿1 小时前
(译文)重温:Karpathy 的 4 条 CLAUDE.md 规则将 Claude 错误率从 41% 降至 11%——历经 30 个代码库后,我又加了 8 条
前端·后端·ai编程
前端那点事1 小时前
Vite+Vue3环境判断终极解法!区分开发/生产环境,告别环境报错
前端·vue.js
源码集结号1 小时前
基于 Spring Boot + JPA + MySQL的上门家政系统代码示例
java·前端·后端