@gmcb/uv-ui 0.2.27 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +95 -141
- package/docs/api/configs/color.md +52 -0
- package/docs/api/index.md +77 -0
- package/docs/api/mixins/mpShare.md +95 -0
- package/docs/api/request/apiManage.md +88 -0
- package/docs/api/request/http.md +451 -0
- package/docs/api/utils/colorSwitch.md +78 -0
- package/docs/api/utils/debounce.md +104 -0
- package/docs/api/utils/fastUse.md +246 -0
- package/docs/api/utils/getRect.md +238 -0
- package/docs/api/utils/guid.md +41 -0
- package/docs/api/utils/index.md +55 -0
- package/docs/api/utils/intro.md +25 -0
- package/docs/api/utils/object.md +171 -0
- package/docs/api/utils/queryParams.md +68 -0
- package/docs/api/utils/random.md +23 -0
- package/docs/api/utils/randomArray.md +28 -0
- package/docs/api/utils/route.md +121 -0
- package/docs/api/utils/test.md +237 -0
- package/docs/api/utils/time.md +81 -0
- package/docs/api/utils/trim.md +24 -0
- package/docs/components/actionSheet.md +236 -0
- package/docs/components/addQQGroup.md +5 -0
- package/docs/components/album.md +91 -0
- package/docs/components/alert.md +83 -0
- package/docs/components/avatar.md +152 -0
- package/docs/components/backTop.md +181 -0
- package/docs/components/badge.md +117 -0
- package/docs/components/button.md +196 -0
- package/docs/components/calendar.md +398 -0
- package/docs/components/calendars.md +294 -0
- package/docs/components/cell.md +185 -0
- package/docs/components/checkbox.md +281 -0
- package/docs/components/circleProgress.md +5 -0
- package/docs/components/code.md +162 -0
- package/docs/components/codeInput.md +175 -0
- package/docs/components/collapse.md +250 -0
- package/docs/components/color.md +324 -0
- package/docs/components/common.md +126 -0
- package/docs/components/countDown.md +166 -0
- package/docs/components/countTo.md +140 -0
- package/docs/components/datetimePicker.md +283 -0
- package/docs/components/diff1.x.md +190 -0
- package/docs/components/divider.md +88 -0
- package/docs/components/downloadSetting.md +54 -0
- package/docs/components/dropDown.md +375 -0
- package/docs/components/empty.md +99 -0
- package/docs/components/feature.md +261 -0
- package/docs/components/form.md +736 -0
- package/docs/components/gap.md +49 -0
- package/docs/components/grid.md +225 -0
- package/docs/components/icon.md +101 -0
- package/docs/components/image.md +182 -0
- package/docs/components/index.md +110 -0
- package/docs/components/indexList.md +133 -0
- package/docs/components/input.md +250 -0
- package/docs/components/install.md +59 -0
- package/docs/components/intro.md +32 -0
- package/docs/components/keyboard.md +226 -0
- package/docs/components/layout.md +310 -0
- package/docs/components/line.md +85 -0
- package/docs/components/lineProgress.md +141 -0
- package/docs/components/link.md +89 -0
- package/docs/components/list.md +223 -0
- package/docs/components/loadMore.md +140 -0
- package/docs/components/loadingIcon.md +144 -0
- package/docs/components/loadingPage.md +92 -0
- package/docs/components/modal.md +230 -0
- package/docs/components/more.md +13 -0
- package/docs/components/navbar.md +192 -0
- package/docs/components/noNetwork.md +116 -0
- package/docs/components/noticeBar.md +131 -0
- package/docs/components/notify.md +204 -0
- package/docs/components/npmSetting.md +64 -0
- package/docs/components/numberBox.md +257 -0
- package/docs/components/nvue.md +170 -0
- package/docs/components/overlay.md +117 -0
- package/docs/components/parse.md +204 -0
- package/docs/components/pickColor.md +112 -0
- package/docs/components/picker.md +357 -0
- package/docs/components/popup.md +221 -0
- package/docs/components/problem.md +300 -0
- package/docs/components/qrcode.md +169 -0
- package/docs/components/quickstart.md +33 -0
- package/docs/components/radio.md +256 -0
- package/docs/components/rate.md +128 -0
- package/docs/components/read.md +163 -0
- package/docs/components/readMore.md +227 -0
- package/docs/components/resource.md +17 -0
- package/docs/components/scrollList.md +218 -0
- package/docs/components/search.md +160 -0
- package/docs/components/setting.md +111 -0
- package/docs/components/settingDesc.md +66 -0
- package/docs/components/skeleton.md +105 -0
- package/docs/components/skeletons.md +323 -0
- package/docs/components/slider.md +157 -0
- package/docs/components/steps.md +189 -0
- package/docs/components/sticky.md +76 -0
- package/docs/components/subsection.md +183 -0
- package/docs/components/swipeAction.md +279 -0
- package/docs/components/swiper.md +352 -0
- package/docs/components/switch.md +216 -0
- package/docs/components/tabbar.md +263 -0
- package/docs/components/table.md +5 -0
- package/docs/components/tabs.md +364 -0
- package/docs/components/tag.md +227 -0
- package/docs/components/testPic.md +20 -0
- package/docs/components/text.md +157 -0
- package/docs/components/textarea.md +121 -0
- package/docs/components/toast.md +124 -0
- package/docs/components/tooltip.md +98 -0
- package/docs/components/transition.md +404 -0
- package/docs/components/upload.md +253 -0
- package/docs/components/vtabs.md +332 -0
- package/docs/components/vueUse.md +45 -0
- package/docs/components/vuexDetail.md +103 -0
- package/docs/components/waterfall.md +651 -0
- package/docs/faq/index.md +53 -0
- package/docs/guide/codeHint.md +44 -0
- package/docs/guide/customIcon.md +168 -0
- package/docs/guide/demo.md +92 -0
- package/docs/guide/design.md +56 -0
- package/docs/guide/globalVariable.md +239 -0
- package/docs/guide/i18n.md +194 -0
- package/docs/guide/index.md +28 -0
- package/docs/guide/note.md +74 -0
- package/docs/guide/safeAreaInset.md +64 -0
- package/docs/guide/theme.md +67 -0
- package/docs/index.md +88 -0
- package/libs/config/config.js +0 -10
- package/libs/css/color.scss +15 -14
- package/package.json +7 -2
- package/theme.scss +2 -1
|
@@ -0,0 +1,736 @@
|
|
|
1
|
+
## Form 表单 <to-api/>
|
|
2
|
+
|
|
3
|
+
<demo-model url="/pages/componentsB/form/form"></demo-model>
|
|
4
|
+
|
|
5
|
+
::: tip ✈
|
|
6
|
+
|
|
7
|
+
**组件名:uv-form**
|
|
8
|
+
|
|
9
|
+
[点击下载&安装](https://ext.dcloud.net.cn/plugin?name=uv-form)
|
|
10
|
+
|
|
11
|
+
:::
|
|
12
|
+
|
|
13
|
+
此组件一般用于表单场景,可以配置Input输入框,Select弹出框,进行表单验证等。
|
|
14
|
+
|
|
15
|
+
### 平台兼容性
|
|
16
|
+
|
|
17
|
+
|App(vue)|App(nvue)|H5|小程序|VUE2|VUE3|
|
|
18
|
+
|:-:|:-:|:-:|:-:|:-:|:-:|
|
|
19
|
+
|√|√|√|√|√|√|
|
|
20
|
+
|
|
21
|
+
::: warning 注意事项:
|
|
22
|
+
|
|
23
|
+
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
|
|
24
|
+
|
|
25
|
+
1. 组件上的ref建议不要和组件重名,否则vue3的setup语法糖会报错无法正常显示,详情见[常见问题-使用的ref与组件名重名-在vue3的setup语法糖中会报错](/components/problem.html#三、使用的ref与组件名重名-在vue3的setup语法糖中会报错)
|
|
26
|
+
2. 在实现查看密码等功能时,可能会子组件uv-form-item上使用v-if进行判断显示和隐藏,这时建议给uv-form-item加上key值,否则可能出现 `type="password"` 变成 `type="text"` 会失效
|
|
27
|
+
3. 在app-nvue模式下,如果form-item节点下的input设置了disabled或readonly状态,会导致节点上的事件无效,所以这种情况下的解决方案:给input套一层view,再在view中用一个节点进行定位,目的就是把input给遮住,这样就可以解决问题。没办法,nvue太恶心了。
|
|
28
|
+
|
|
29
|
+
:::
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### 基本使用
|
|
33
|
+
|
|
34
|
+
此组件一般是用于表单验证使用,每一个表单域由一个`uv-form-item`组成,表单域中可以放置`uv-input`、`uv-textarea`、`uv-checkbox`、`uv-radio`、`uv-switch`等。
|
|
35
|
+
|
|
36
|
+
- 在表单组中,通过`model`参数绑定一个对象,这个对象的属性为各个`uv-form-item`内组件的对应变量。
|
|
37
|
+
- 由于表单验证和绑定表单规则时,需要通过`ref`操作,故这里需要给`form`组件声明`ref="form"`属性。
|
|
38
|
+
- 关于`uv-from-item`内其他可能包含的诸如`input`、`radio`等组件,请见各自组件的相关文档说明。
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<template>
|
|
43
|
+
<view>
|
|
44
|
+
<uv-form labelPosition="left" :model="model1" :rules="rules" ref="form">
|
|
45
|
+
<uv-form-item label="姓名" prop="userInfo.name" borderBottom>
|
|
46
|
+
<uv-input v-model="model1.userInfo.name" border="none">
|
|
47
|
+
</uv-input>
|
|
48
|
+
</uv-form-item>
|
|
49
|
+
<uv-form-item label="性别" prop="userInfo.sex" borderBottom @click="showSexSelect">
|
|
50
|
+
<uv-input v-model="model1.userInfo.sex" disabled disabledColor="#ffffff" placeholder="请选择性别" border="none">
|
|
51
|
+
</uv-input>
|
|
52
|
+
<template v-slot:right>
|
|
53
|
+
<uv-icon name="arrow-right"></uv-icon>
|
|
54
|
+
</template>
|
|
55
|
+
</uv-form-item>
|
|
56
|
+
<uv-button type="primary" text="提交" customStyle="margin-top: 10px" @click="submit"></uv-button>
|
|
57
|
+
<uv-button type="error" text="重置" customStyle="margin-top: 10px" @click="reset"></uv-button>
|
|
58
|
+
</uv-form>
|
|
59
|
+
<uv-action-sheet ref="sexSelect" :actions="actions" title="请选择性别" description="如果选择保密会报错" @select="sexSelect">
|
|
60
|
+
</uv-action-sheet>
|
|
61
|
+
</view>
|
|
62
|
+
</template>
|
|
63
|
+
<script setup>
|
|
64
|
+
import { ref } from "vue";
|
|
65
|
+
const model1 = ref({
|
|
66
|
+
userInfo: {
|
|
67
|
+
name: 'uv-ui',
|
|
68
|
+
sex: ''
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
const actions = ref([{
|
|
72
|
+
name: '男'
|
|
73
|
+
}, {
|
|
74
|
+
name: '女'
|
|
75
|
+
}, {
|
|
76
|
+
name: '保密'
|
|
77
|
+
}]);
|
|
78
|
+
const rules = ref({
|
|
79
|
+
'userInfo.name': {
|
|
80
|
+
type: 'string',
|
|
81
|
+
required: true,
|
|
82
|
+
message: '请填写姓名',
|
|
83
|
+
trigger: ['blur', 'change']
|
|
84
|
+
},
|
|
85
|
+
'userInfo.sex': {
|
|
86
|
+
type: 'string',
|
|
87
|
+
max: 1,
|
|
88
|
+
required: true,
|
|
89
|
+
message: '请选择男或女',
|
|
90
|
+
trigger: ['blur', 'change']
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const radio = ref('');
|
|
94
|
+
const switchVal = ref(false);
|
|
95
|
+
const form = ref(null);
|
|
96
|
+
function submit() {
|
|
97
|
+
// 如果有错误,会在catch中返回报错信息数组,校验通过则在then中返回true
|
|
98
|
+
form.value.validate().then(res => {
|
|
99
|
+
uni.showToast({
|
|
100
|
+
icon: 'success',
|
|
101
|
+
title: '校验通过'
|
|
102
|
+
});
|
|
103
|
+
}).catch(errors => {
|
|
104
|
+
uni.showToast({
|
|
105
|
+
icon: 'error',
|
|
106
|
+
title: '校验失败'
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function reset() {
|
|
111
|
+
form.value.resetFields();
|
|
112
|
+
form.value.clearValidate();
|
|
113
|
+
}
|
|
114
|
+
function showSexSelect() {
|
|
115
|
+
sexSelect.value.open();
|
|
116
|
+
hideKeyboard();
|
|
117
|
+
}
|
|
118
|
+
function sexSelect(e) {
|
|
119
|
+
model1.value.userInfo.sex = e.name;
|
|
120
|
+
// 对部分表单字段进行校验
|
|
121
|
+
form.value.validateField('userInfo.sex', err => {
|
|
122
|
+
// 处理错误后的逻辑
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function hideKeyboard() {
|
|
126
|
+
uni.hideKeyboard();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
</script>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
从上面的示例我们可以看到,`rules`中的属性名和`form`的属性名是一致的,同时传递给`uv-form-item`的`prop`参数绑定的也是相同的属性名,注意这里`prop`参数绑定的是
|
|
133
|
+
字符串(属性名),而不是一个变量。
|
|
134
|
+
|
|
135
|
+
### Tips
|
|
136
|
+
|
|
137
|
+
::: warning 注意:
|
|
138
|
+
|
|
139
|
+
某些小程序编译场景可能不支持 props 传递函数。为了保持兼容,可以通过 `setRules` 方法设置规则。如下:
|
|
140
|
+
```vue
|
|
141
|
+
<script setup>
|
|
142
|
+
import { ref } from 'vue';
|
|
143
|
+
import { onReady } from '@dcloudio/uni-app';
|
|
144
|
+
|
|
145
|
+
const form = ref(null);
|
|
146
|
+
const rules = ref({});
|
|
147
|
+
|
|
148
|
+
onReady(() => {
|
|
149
|
+
// onReady 为 uni-app 支持的生命周期之一
|
|
150
|
+
form.value?.setRules(rules.value);
|
|
151
|
+
});
|
|
152
|
+
</script>
|
|
153
|
+
```
|
|
154
|
+
:::
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
### Form-item组件说明
|
|
158
|
+
|
|
159
|
+
此组件一般需要搭配`Form`组件使用,也可以单独搭配`Input`等组件使用,由于此组件参数较多,这里只对其中参数最简要介绍,其余请见底部的[Form-item Props](/components/form.html#form-item-props)说明:
|
|
160
|
+
|
|
161
|
+
- `prop`为传入`Form`组件的`model`中的属性字段,如果需要表单验证,此属性是必填的。
|
|
162
|
+
- `labelPosition`可以配置左侧"label"的对齐方式,可选为`left`和`top`。
|
|
163
|
+
- `borderBottom`是否显示表单域的下划线,如果给`Input`组件配置了边框,可以将此属性设置为`false`,从而隐藏默认的下划线。
|
|
164
|
+
- 如果想在表单域配置左侧图标或小图片,可以通过`leftIcon`参数实现。
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
### 验证规则 - rules属性示例[1]
|
|
168
|
+
|
|
169
|
+
组件验证部分采用了[async-validator](https://github.com/yiminghe/async-validator),一个字段可以设置多个内置规则,以及自定义规则,触发方式等,
|
|
170
|
+
每个字段的验证规则为一个数组,数组的每一个元素对象为其中一条规则(一个字段的验证可以配置多个规则),如下:
|
|
171
|
+
|
|
172
|
+
```js
|
|
173
|
+
rules: {
|
|
174
|
+
'userInfo.name': {
|
|
175
|
+
type: 'string',
|
|
176
|
+
required: true,
|
|
177
|
+
message: '请填写姓名',
|
|
178
|
+
trigger: ['blur', 'change']
|
|
179
|
+
},
|
|
180
|
+
code: {
|
|
181
|
+
type: 'string',
|
|
182
|
+
required: true,
|
|
183
|
+
len: 4,
|
|
184
|
+
message: '请填写4位验证码',
|
|
185
|
+
trigger: ['blur']
|
|
186
|
+
},
|
|
187
|
+
'userInfo.sex': {
|
|
188
|
+
type: 'string',
|
|
189
|
+
max: 1,
|
|
190
|
+
required: true,
|
|
191
|
+
message: '请选择男或女',
|
|
192
|
+
trigger: ['blur', 'change']
|
|
193
|
+
},
|
|
194
|
+
radiovalue1: {
|
|
195
|
+
type: 'string',
|
|
196
|
+
min: 1,
|
|
197
|
+
max: 2,
|
|
198
|
+
message: '生命是美好的,弃治疗',
|
|
199
|
+
trigger: ['change']
|
|
200
|
+
},
|
|
201
|
+
checkboxValue1: {
|
|
202
|
+
type: 'array',
|
|
203
|
+
min: 2,
|
|
204
|
+
required: true,
|
|
205
|
+
message: '不能太宅,至少选两项',
|
|
206
|
+
trigger: ['change']
|
|
207
|
+
},
|
|
208
|
+
intro: {
|
|
209
|
+
type: 'string',
|
|
210
|
+
min: 3,
|
|
211
|
+
required: true,
|
|
212
|
+
message: '不低于3个字',
|
|
213
|
+
trigger: ['change']
|
|
214
|
+
},
|
|
215
|
+
hotel: {
|
|
216
|
+
type: 'string',
|
|
217
|
+
min: 2,
|
|
218
|
+
required: true,
|
|
219
|
+
message: '请选择住店时间',
|
|
220
|
+
trigger: ['change']
|
|
221
|
+
},
|
|
222
|
+
'userInfo.birthday': {
|
|
223
|
+
type: 'string',
|
|
224
|
+
required: true,
|
|
225
|
+
message: '请选择生日',
|
|
226
|
+
trigger: ['change']
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
### 验证规则 - rules属性说明[2]
|
|
233
|
+
|
|
234
|
+
每一个验证规则中,可以配置多个属性,下面对常用的属性进行讲解,更具体的可以查看[async-validator](https://github.com/yiminghe/async-validator)的文档说明:
|
|
235
|
+
|
|
236
|
+
- `trigger`{String | Array}:触发校验的方式有2种:
|
|
237
|
+
- change:字段值发生变化时校验
|
|
238
|
+
- blur:输入框失去焦点时触发
|
|
239
|
+
- 如果同时监听两种方式,需要写成数组形式:`['change', 'blur']`
|
|
240
|
+
|
|
241
|
+
- `type`{String}
|
|
242
|
+
内置校验规则,如这些规则无法满足需求,可以使用正则匹配、或者使用`validator`自定义方法并结合uv-ui自带[验证规则](/api/utils/test.html)。
|
|
243
|
+
- string:必须是 `string` 类型,默认类型
|
|
244
|
+
- number:必须是 `number` 类型
|
|
245
|
+
- boolean:必须是 `boolean` 类型
|
|
246
|
+
- method:必须是 `function` 类型
|
|
247
|
+
- regexp:必须是 `regexp` 类型,这里的正则,指的是判断字段的内容是否一个正则表达式,而不是用这个正则去匹配字段值
|
|
248
|
+
- integer:必须是`整数`类型
|
|
249
|
+
- float:必须是`浮点数`类型
|
|
250
|
+
- array:必须是 `array` 类型
|
|
251
|
+
- object:必须是 `object` 类型
|
|
252
|
+
- enum:必须出现在 `enmu` 指定的值中
|
|
253
|
+
- date:必须是 `date` 类型
|
|
254
|
+
- url:必须是 `url` 类型
|
|
255
|
+
- hex:必须是 `16` 进制类型
|
|
256
|
+
- email:必须是 `email` 类型
|
|
257
|
+
- any:任意类型
|
|
258
|
+
|
|
259
|
+
- `required`
|
|
260
|
+
布尔值,是否必填,配置此参数不会显示输入框左边的必填星号,如需要,请配置`uv-form-item`的`required`为`true`,注意:如需在`uv-form-item`标签内显示星号,需要给予`swiper-item`第一个根节点一定的`margin`样式
|
|
261
|
+
|
|
262
|
+
- `pattern`
|
|
263
|
+
要求此参数值为一个正则表达式,如: /\d+/,**不能**带引号,如:"/\d+/",组件会对字段进行正则判断,返回结果。
|
|
264
|
+
|
|
265
|
+
- `min`
|
|
266
|
+
最小值,如果字段类型为字符串和数组,会取字符串长度与数组长度(length)与`min`比较,如果字段是数值,则直接与`min`比较。
|
|
267
|
+
|
|
268
|
+
- `max`
|
|
269
|
+
最大值,规则同`min`参数
|
|
270
|
+
|
|
271
|
+
- `len`
|
|
272
|
+
指定长度,规则同`min`,优先级高于`min`和`max`
|
|
273
|
+
|
|
274
|
+
- `enum`{Array}
|
|
275
|
+
指定的值,配合 type: 'enum' 使用
|
|
276
|
+
|
|
277
|
+
- `whitespace`{Boolean}
|
|
278
|
+
设置该值为`true`,如果字段值内容都为空格,默认无法通过`required: true`校验
|
|
279
|
+
|
|
280
|
+
- `transform`{Function},校验前对值进行转换,函数的参数为当前值,返回值为改变后的值,参数如如下:
|
|
281
|
+
- `value`:当前校验字段的值
|
|
282
|
+
|
|
283
|
+
- `message`
|
|
284
|
+
校验不通过时的提示信息
|
|
285
|
+
|
|
286
|
+
- `validator`{Function}:自定义**同步**校验函数,参数如下:
|
|
287
|
+
- `rule`:当前校验字段在 rules 中所对应的校验规则
|
|
288
|
+
- `value`:当前校验字段的值
|
|
289
|
+
- `callback`:校验完成时的回调,一般无需执行callback,返回`true`(校验通过)或者`false`(校验失败)即可
|
|
290
|
+
|
|
291
|
+
- `asyncValidator`{Function}:自定义**异步**校验函数,参数如下:
|
|
292
|
+
- `rule`:当前校验字段在 rules 中所对应的校验规则
|
|
293
|
+
- `value`:当前校验字段的值
|
|
294
|
+
- `callback`:校验完成时的回调,执行完异步操作(比如向后端请求数据验证),如果不通过,需要callback(new Error('提示错误信息')),如果校验通过,执行callback()即可
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
### 验证规则 - 配合uvui内置自定义效验规则[3]
|
|
299
|
+
|
|
300
|
+
uv-ui在JS板块的[Test 规则校验](/api/utils/test.html)中有大量内置的验证规则,这些规则对表单验证来说,属于**自定义规则**,故需要用到上方规则属性的
|
|
301
|
+
`validator`自定义验证函数,这里做一个详细说明。
|
|
302
|
+
|
|
303
|
+
我们知道uv-ui有自带的判断手机号的验证方法`uni.$uv.test.mobile(value)`,但是[async-validator](https://github.com/yiminghe/async-validator)没有
|
|
304
|
+
内置判断手机号的规则,所以将二者结合使用:
|
|
305
|
+
|
|
306
|
+
::: warning 温馨提示
|
|
307
|
+
1. 使用uni上挂载的uv-ui内置方法,需要根据[扩展配置 - JS工具库](/components/setting.html)进行相应的配置,否则直接会报错!
|
|
308
|
+
2. 某些平台可能不支持 props 传递函数,可以通过调用方法解决,请注意上面的 [Tips](/components/form.html#tips)。
|
|
309
|
+
3. 再次说明:自定义效验未生效,请在onReady中添加 `form.value?.setRules(rules)`
|
|
310
|
+
:::
|
|
311
|
+
|
|
312
|
+
```vue
|
|
313
|
+
<template>
|
|
314
|
+
<view>
|
|
315
|
+
<uv-form :model="form" :rules="rules" ref="form">
|
|
316
|
+
<uv-form-item label="电话" prop="mobile">
|
|
317
|
+
<uv-input v-model="form.mobile" placeholder="请输入电话" />
|
|
318
|
+
</uv-form-item>
|
|
319
|
+
</uv-form>
|
|
320
|
+
<uv-button @click="submit">提交</uv-button>
|
|
321
|
+
</view>
|
|
322
|
+
</template>
|
|
323
|
+
<script setup>
|
|
324
|
+
import { ref } from "vue";
|
|
325
|
+
import { onReady } from "@dcloudio/uni-app";
|
|
326
|
+
const form = ref({
|
|
327
|
+
mobile: ''
|
|
328
|
+
});
|
|
329
|
+
const rules = ref({
|
|
330
|
+
mobile: [{
|
|
331
|
+
required: true,
|
|
332
|
+
message: '此为必填字段',
|
|
333
|
+
// blur和change事件触发检验
|
|
334
|
+
trigger: ['blur', 'change']
|
|
335
|
+
}, {
|
|
336
|
+
// 自定义验证函数,见上说明,注意这里面的逻辑不能出现语法报错,否则可能导致不验证
|
|
337
|
+
validator: (rule, value, callback) => {
|
|
338
|
+
// 此处业务逻辑省略
|
|
339
|
+
// 返回true表校验通过,返回false表示不通过
|
|
340
|
+
return true;
|
|
341
|
+
},
|
|
342
|
+
message: '电话号码格式错误',
|
|
343
|
+
trigger: ['blur']
|
|
344
|
+
}]
|
|
345
|
+
});
|
|
346
|
+
function submit() {
|
|
347
|
+
form.value.validate().then(res => {
|
|
348
|
+
uni.showToast({
|
|
349
|
+
icon: 'success',
|
|
350
|
+
title: '校验通过'
|
|
351
|
+
});
|
|
352
|
+
}).catch(errors => {
|
|
353
|
+
uni.showToast({
|
|
354
|
+
icon: 'error',
|
|
355
|
+
title: '校验失败'
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
onReady(() => {
|
|
360
|
+
form.value.setRules(rules.value);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
</script>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 实战案例 - 配合uv-upload上传进行验证[4]
|
|
367
|
+
|
|
368
|
+
该案例说明理论上可以验证任何形式的数据,与上传组件一起验证就是一个很常见的案例,其实只需要将rules中的值定义好即可,验证的过程就是判断有没有值。
|
|
369
|
+
|
|
370
|
+
如下示例:删除图片后要做验证,则需要配置 `validateField` 进行单独验证,这样体验更佳。
|
|
371
|
+
|
|
372
|
+
```vue
|
|
373
|
+
<template>
|
|
374
|
+
<view style="padding: 30rpx;">
|
|
375
|
+
<uv-form :model="form" :rules="rules" ref="form">
|
|
376
|
+
<uv-form-item label="姓名" prop="username">
|
|
377
|
+
<uv-input v-model="form.username" placeholder="请输入姓名" />
|
|
378
|
+
</uv-form-item>
|
|
379
|
+
<uv-form-item label="照片" prop="pics">
|
|
380
|
+
<uv-upload
|
|
381
|
+
:fileList="fileList"
|
|
382
|
+
name="1"
|
|
383
|
+
multiple
|
|
384
|
+
:maxCount="9"
|
|
385
|
+
@afterRead="afterRead"
|
|
386
|
+
@delete="deletePic"
|
|
387
|
+
:previewFullImage="true"
|
|
388
|
+
></uv-upload>
|
|
389
|
+
</uv-form-item>
|
|
390
|
+
</uv-form>
|
|
391
|
+
<uv-button @click="submit">提交</uv-button>
|
|
392
|
+
</view>
|
|
393
|
+
</template>
|
|
394
|
+
<script setup>
|
|
395
|
+
import { ref } from "vue";
|
|
396
|
+
const fileList = ref([]);
|
|
397
|
+
const form = ref({
|
|
398
|
+
username: '',
|
|
399
|
+
pics: []
|
|
400
|
+
});
|
|
401
|
+
const rules = ref({
|
|
402
|
+
username: [{
|
|
403
|
+
required: true,
|
|
404
|
+
message: '此为必填字段',
|
|
405
|
+
trigger: ['blur', 'change']
|
|
406
|
+
}],
|
|
407
|
+
pics: {
|
|
408
|
+
type: 'array',
|
|
409
|
+
required: true,
|
|
410
|
+
message: '请上传照片',
|
|
411
|
+
trigger: ['blur', 'change']
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
function submit() {
|
|
415
|
+
form.value.validate().then(res => {
|
|
416
|
+
uni.showToast({
|
|
417
|
+
icon: 'success',
|
|
418
|
+
title: '校验通过'
|
|
419
|
+
});
|
|
420
|
+
}).catch(errors => {
|
|
421
|
+
uni.showToast({
|
|
422
|
+
icon: 'error',
|
|
423
|
+
title: '校验失败'
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
function afterRead(e) {
|
|
428
|
+
// 这里直接模拟上传成功,这里的真实逻辑参考uv-upload组件示例
|
|
429
|
+
setTimeout(() => {
|
|
430
|
+
fileList.value = [{
|
|
431
|
+
url: 'https://via.placeholder.com/100x100.png/3c9cff'
|
|
432
|
+
}, {
|
|
433
|
+
url: 'https://via.placeholder.com/100x100.png/ff0000'
|
|
434
|
+
}];
|
|
435
|
+
form.value.pics = fileList.value;
|
|
436
|
+
form.value.validateField('pics', err => {
|
|
437
|
+
// 处理错误后的逻辑
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
function deletePic(e) {
|
|
442
|
+
fileList.value.splice(e.index, 1);
|
|
443
|
+
form.value.validateField('pics', err => {
|
|
444
|
+
// 处理错误后的逻辑
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
</script>
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### 实战案例 - 动态表单的基本用法[5]
|
|
452
|
+
|
|
453
|
+
在实际开发中,有需求动态表单,实际上也是可以通过js去实现的,核心思路是将data部分的值进行动态添加。如下示例:
|
|
454
|
+
|
|
455
|
+
```vue
|
|
456
|
+
<template>
|
|
457
|
+
<view>
|
|
458
|
+
<uv-form labelPosition="left" :model="model" :rules="rules" ref="form">
|
|
459
|
+
<template v-for="(item,index) in list">
|
|
460
|
+
<uv-form-item :label="item.label" :prop="item.name" borderBottom>
|
|
461
|
+
<uv-input v-model="model[item.name]" border="none">
|
|
462
|
+
</uv-input>
|
|
463
|
+
</uv-form-item>
|
|
464
|
+
</template>
|
|
465
|
+
<uv-button type="info" text="添加字段" customStyle="margin-top: 10px" @click="add"></uv-button>
|
|
466
|
+
<uv-button type="primary" text="提交" customStyle="margin-top: 10px" @click="submit"></uv-button>
|
|
467
|
+
<uv-button type="error" text="重置" customStyle="margin-top: 10px" @click="reset"></uv-button>
|
|
468
|
+
</uv-form>
|
|
469
|
+
</view>
|
|
470
|
+
</template>
|
|
471
|
+
<script setup>
|
|
472
|
+
import { ref } from "vue";
|
|
473
|
+
import { onLoad } from "@dcloudio/uni-app";
|
|
474
|
+
const model = ref({});
|
|
475
|
+
const list = ref([]);
|
|
476
|
+
const rules = ref({});
|
|
477
|
+
const form = ref(null);
|
|
478
|
+
function add() {
|
|
479
|
+
const addData = {
|
|
480
|
+
name: 'demo',
|
|
481
|
+
label: '添加的项',
|
|
482
|
+
rules: {
|
|
483
|
+
type: 'string',
|
|
484
|
+
required: true,
|
|
485
|
+
message: '请填写添加项',
|
|
486
|
+
trigger: ['blur', 'change']
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
model.value[addData.name] = '';
|
|
490
|
+
rules.value[addData.name] = addData.rules;
|
|
491
|
+
list.value.push(addData);
|
|
492
|
+
}
|
|
493
|
+
function getData() {
|
|
494
|
+
return [{
|
|
495
|
+
name: 'name',
|
|
496
|
+
label: '姓名',
|
|
497
|
+
rules: {
|
|
498
|
+
type: 'string',
|
|
499
|
+
required: true,
|
|
500
|
+
message: '请填写姓名',
|
|
501
|
+
trigger: ['blur', 'change']
|
|
502
|
+
}
|
|
503
|
+
}, {
|
|
504
|
+
name: 'age',
|
|
505
|
+
label: '年龄',
|
|
506
|
+
rules: {
|
|
507
|
+
type: 'string',
|
|
508
|
+
required: true,
|
|
509
|
+
message: '请填写年龄',
|
|
510
|
+
trigger: ['blur', 'change']
|
|
511
|
+
}
|
|
512
|
+
}, {
|
|
513
|
+
name: 'like',
|
|
514
|
+
label: '爱好',
|
|
515
|
+
rules: {
|
|
516
|
+
type: 'string',
|
|
517
|
+
required: true,
|
|
518
|
+
message: '请填写兴趣爱好',
|
|
519
|
+
trigger: ['blur', 'change']
|
|
520
|
+
}
|
|
521
|
+
}];
|
|
522
|
+
}
|
|
523
|
+
function submit() {
|
|
524
|
+
form.value.validate().then(res => {
|
|
525
|
+
uni.showToast({
|
|
526
|
+
icon: 'success',
|
|
527
|
+
title: '校验通过'
|
|
528
|
+
});
|
|
529
|
+
}).catch(errors => {
|
|
530
|
+
uni.showToast({
|
|
531
|
+
icon: 'error',
|
|
532
|
+
title: '校验失败'
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
function reset() {
|
|
537
|
+
form.value.resetFields();
|
|
538
|
+
form.value.clearValidate();
|
|
539
|
+
}
|
|
540
|
+
function hideKeyboard() {
|
|
541
|
+
uni.hideKeyboard();
|
|
542
|
+
}
|
|
543
|
+
onLoad(() => {
|
|
544
|
+
const data = getData();
|
|
545
|
+
data.forEach(item => {
|
|
546
|
+
model.value[item.name] = '';
|
|
547
|
+
rules.value[item.name] = item.rules;
|
|
548
|
+
});
|
|
549
|
+
list.value = data;
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
</script>
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### 验证规则 - 综合实战[6]
|
|
556
|
+
|
|
557
|
+
上面讲述了[async-validator](https://github.com/yiminghe/async-validator)的规则和配置,以及uv-ui内置规则的结合使用,下面我们进行一个综合
|
|
558
|
+
实战示例,要入对某一个字段进行如下验证(验证实现有多种方法,下方仅为引导示例,非唯一,或最优做法):
|
|
559
|
+
|
|
560
|
+
1. 必填,同时可接受`change`和`blur`触发校验:配置`required`参数为`true`,同时配置`trigger`为`[change, blur]`
|
|
561
|
+
2. 必须为字母或字符串,校验前先将字段值转为字符串类型:通过`pattern`参数配置正则:/^[0-9a-zA-Z]*$/g,通过`transform`参数在校验前对字段值转换为字符串
|
|
562
|
+
3. 长度6-8个字符之间:通过 配置`min`为6,`max`为8
|
|
563
|
+
4. 需要包含字母"A":使用uv-ui的`uni.$uv.test.contains()`方法,并结合`validator`自定义函数实现
|
|
564
|
+
5. 异步校验,输入完账号,输入框失去焦点时,向后端请求该账号是否已存在:通过上方的`asyncValidator`异步函数进行验证。
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
综上,我们可以得出如下的一个配置规则(仅为综合演示,非最优做法):
|
|
568
|
+
|
|
569
|
+
```js
|
|
570
|
+
rules: {
|
|
571
|
+
name: [
|
|
572
|
+
// 必填规则
|
|
573
|
+
{
|
|
574
|
+
required: true,
|
|
575
|
+
message: '此为必填字段',
|
|
576
|
+
// blur和change事件触发检验
|
|
577
|
+
trigger: ['blur', 'change'],
|
|
578
|
+
},
|
|
579
|
+
// 正则判断为字母或数字
|
|
580
|
+
{
|
|
581
|
+
pattern: /^[0-9a-zA-Z]*$/g,
|
|
582
|
+
// 正则检验前先将值转为字符串
|
|
583
|
+
transform(value) {
|
|
584
|
+
return String(value);
|
|
585
|
+
},
|
|
586
|
+
message: '只能包含字母或数字'
|
|
587
|
+
},
|
|
588
|
+
// 6-8个字符之间的判断
|
|
589
|
+
{
|
|
590
|
+
min: 6,
|
|
591
|
+
max: 8,
|
|
592
|
+
message: '长度在6-8个字符之间'
|
|
593
|
+
},
|
|
594
|
+
// 自定义规则判断是否包含字母"A"
|
|
595
|
+
{
|
|
596
|
+
validator: (rule, value, callback) => {
|
|
597
|
+
return uni.$uv.test.contains(value, "A");
|
|
598
|
+
},
|
|
599
|
+
message: '必须包含字母"A"'
|
|
600
|
+
},
|
|
601
|
+
// 校验用户是否已存在
|
|
602
|
+
{
|
|
603
|
+
asyncValidator: (rule, value, callback) => {
|
|
604
|
+
uni.$uv.http.post('/xxx/xxx', {name: value}).then(res => {
|
|
605
|
+
// 如果验证不通过,需要在callback()抛出new Error('错误提示信息')
|
|
606
|
+
if(res.error) {
|
|
607
|
+
callback(new Error('姓名重复'));
|
|
608
|
+
} else {
|
|
609
|
+
// 如果校验通过,也要执行callback()回调
|
|
610
|
+
callback();
|
|
611
|
+
}
|
|
612
|
+
})
|
|
613
|
+
},
|
|
614
|
+
// 如果是异步校验,无需写message属性,错误的信息通过Error抛出即可
|
|
615
|
+
// message: 'xxx'
|
|
616
|
+
}
|
|
617
|
+
]
|
|
618
|
+
}
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### 校验错误提示方式
|
|
622
|
+
|
|
623
|
+
uv-ui提供了多种校验的错误提示方式,传递给`Form`组件的`errorType`参数:
|
|
624
|
+
- message:默认为输入框下方用文字进行提示
|
|
625
|
+
- none:不会进行任何提示
|
|
626
|
+
- border-bottom:配置作用域底部的下划线显示为红色,要求给form-item设置了borderBottom=true才有效
|
|
627
|
+
- toast:以"toast"提示的方式弹出错误信息,每次只弹出最前面的那个表单域的错误信息
|
|
628
|
+
|
|
629
|
+
```vue
|
|
630
|
+
<template>
|
|
631
|
+
<uv-form :errorType="errorType">
|
|
632
|
+
......
|
|
633
|
+
</uv-form>
|
|
634
|
+
</template>
|
|
635
|
+
|
|
636
|
+
<script setup>
|
|
637
|
+
import { ref } from "vue";
|
|
638
|
+
const errorType = ref('message');
|
|
639
|
+
|
|
640
|
+
</script>
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### 最终目的 - 进行校验
|
|
644
|
+
|
|
645
|
+
进行了上方的配置和讲解后,进入到最后一步,执行验证:
|
|
646
|
+
需要通过`ref`调用`Form`组件的`validate`方法,该方法回调函数的参数为一个布尔值,`true`为校验通过,否则反之。
|
|
647
|
+
|
|
648
|
+
```js
|
|
649
|
+
// 使用 Promise
|
|
650
|
+
// 对整个表单进行校验,返回一个 Promise
|
|
651
|
+
const form = ref(null);
|
|
652
|
+
|
|
653
|
+
form.value?.validate().then(res => {
|
|
654
|
+
// 成功返回,res 为表单数据
|
|
655
|
+
// 其他逻辑处理
|
|
656
|
+
// ...
|
|
657
|
+
}).catch(error => {
|
|
658
|
+
// 表单校验验失败,error 为具体错误信息
|
|
659
|
+
// 其他逻辑处理
|
|
660
|
+
// ...
|
|
661
|
+
})
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### 完整示例
|
|
665
|
+
|
|
666
|
+
::: tip 完整示例下载地址
|
|
667
|
+
|
|
668
|
+
[https://ext.dcloud.net.cn/plugin?name=uv-ui](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
|
669
|
+
|
|
670
|
+
:::
|
|
671
|
+
|
|
672
|
+
### API
|
|
673
|
+
---
|
|
674
|
+
|
|
675
|
+
### Form Props
|
|
676
|
+
|
|
677
|
+
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
|
678
|
+
|:- |:- |:- |:- |:- |
|
|
679
|
+
| model | 表单数据对象 | Object | - | - |
|
|
680
|
+
| rules | 通过`ref`设置,如果`rules`中有自定义方法等,需要使用`setRules`方法设置规则,见上方[Tips](/components/form.html#tips)说明。具体参数请参考上面的 [验证规则 - rules属性示例[1]](/components/form.html#验证规则-rules属性示例-1) 和 [验证规则 - rules属性说明[2]](/components/form.html#验证规则-rules属性说明-2) | Object | Function | Array | - | - |
|
|
681
|
+
| errorType | 错误的提示方式,见上方[校验错误提示方式](/components/form.html#校验错误提示方式)说明 | String | message | message | toast | border-bottom | none |
|
|
682
|
+
| borderBottom | 是否显示表单域的下划线边框 | Boolean | true | - |
|
|
683
|
+
| labelPosition | 表单域提示文字的位置,`left`-左侧,`top`-上方 | String | left | top | left |
|
|
684
|
+
| labelWidth | 提示文字的宽度,单位px(rpx)。注意:在 `uv-form` 设置此值可能会变化抖动,可以将此值设置到 `uv-form-item` 节点上,效果会有所改善。 | String | Number | 45 | 数值 | auto |
|
|
685
|
+
| labelAlign | lable字体的对齐方式 | String | left | left | center | right|
|
|
686
|
+
| labelStyle | lable的样式,对象形式 | Object | - | - |
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
### Form Methods
|
|
690
|
+
|
|
691
|
+
此方法如要通过ref手动调用
|
|
692
|
+
|
|
693
|
+
| 名称 | 说明 |参数 |
|
|
694
|
+
|:- |:- |:- |
|
|
695
|
+
| validate | 对整个表单进行校验的方法 | - |
|
|
696
|
+
| setRules | 如果`rules`中有自定义方法等,需要用此方法设置`rules`规则,详情参考上面的[Tips](/components/form.html#tips) | Function(rules) |
|
|
697
|
+
| validateField | 对部分表单字段进行校验,回调返回错误,需要自定义后续逻辑 | Function(value, Function(errorsRes)) |
|
|
698
|
+
| resetFields | 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果 | - |
|
|
699
|
+
| clearValidate | 清空校验结果 | Function(props) |
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
### FormItem Props
|
|
703
|
+
|
|
704
|
+
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
|
705
|
+
|:- |:- |:- |:- |:- |
|
|
706
|
+
| label | 左侧提示文字 | String | - | - |
|
|
707
|
+
| prop | 表单域`model`对象的属性名,在使用 validate、resetFields 方法的情况下,该属性是必填的 | String | - | - |
|
|
708
|
+
| borderBottom | 是否显示下边框,如不需要下边框,需同时将`uv-form`的同名参数设置为`false` | String | Boolean | true | true | false |
|
|
709
|
+
| labelWidth | 提示文字的宽度,单位px(rpx),如设置,将覆盖`uv-form`的同名参数 | String | Number | - | - |
|
|
710
|
+
| labelPosition | label的位置 | String | - | left | top |
|
|
711
|
+
| leftIcon | 左侧自定义字体图标(限uv-ui内置图标)或图片地址 | String | - | - |
|
|
712
|
+
| leftIconStyle | 左侧自定义字体图标的样式 | String | Object | - | - |
|
|
713
|
+
| required | 是否显示左边的 * 号,这里仅起展示作用,如需校验必填,请通过`rules`配置必填规则。注意:如果页面没有左右边距,星号可能被遮挡,请根据情况设置样式 | Boolean | false | true | false |
|
|
714
|
+
| customStyle | 自定义样式 | Object | - | - |
|
|
715
|
+
|
|
716
|
+
### FormItem Slots
|
|
717
|
+
|
|
718
|
+
|名称 |说明 |
|
|
719
|
+
|:- |:- |
|
|
720
|
+
| default | form-item 的内容 |
|
|
721
|
+
| right | 右侧自定义内容,可以在此传入一个按钮,用于获取验证码等场景 |
|
|
722
|
+
|
|
723
|
+
### FormItem Events
|
|
724
|
+
|
|
725
|
+
|事件名 |说明 |回调参数 |
|
|
726
|
+
|:- |:- |:- |
|
|
727
|
+
|@click |点击时触发 |- |
|
|
728
|
+
|
|
729
|
+
<style scoped>
|
|
730
|
+
h3[id=form-methods] + p + table thead tr th:nth-child(2){
|
|
731
|
+
width: 60%;
|
|
732
|
+
}
|
|
733
|
+
h3[id=formitem-slots] + table thead tr th:nth-child(2){
|
|
734
|
+
width: 70%;
|
|
735
|
+
}
|
|
736
|
+
</style>
|