Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
京东前端
nutui
提交
95df5bf9
N
nutui
项目概览
京东前端
/
nutui
通知
37
Star
4
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
nutui
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
95df5bf9
编写于
12月 22, 2021
作者:
richard_1015
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(form): add blur、change validate & fix #902
上级
c834450e
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
309 addition
and
44 deletion
+309
-44
src/packages/__VUE/form/common.ts
src/packages/__VUE/form/common.ts
+23
-3
src/packages/__VUE/form/demo.vue
src/packages/__VUE/form/demo.vue
+86
-2
src/packages/__VUE/form/doc.md
src/packages/__VUE/form/doc.md
+112
-35
src/packages/__VUE/formitem/index.scss
src/packages/__VUE/formitem/index.scss
+1
-1
src/packages/__VUE/table/common.ts
src/packages/__VUE/table/common.ts
+1
-1
src/sites/mobile-taro/vue/src/dentry/pages/form/index.vue
src/sites/mobile-taro/vue/src/dentry/pages/form/index.vue
+86
-2
未找到文件。
src/packages/__VUE/form/common.ts
浏览文件 @
95df5bf9
...
...
@@ -44,6 +44,8 @@ export const component = {
prop
:
vnode
.
props
?.[
'
prop
'
],
rules
:
vnode
.
props
?.[
'
rules
'
]
||
[]
});
}
else
if
(
vnode
.
children
?.
length
)
{
task
=
task
.
concat
(
findFormItem
(
vnode
.
children
as
VNode
[]));
}
});
return
task
;
...
...
@@ -66,7 +68,12 @@ export const component = {
});
};
const
value
=
props
.
modelValue
[
prop
];
const
getPropByPath
=
(
obj
:
any
,
keyPath
:
string
)
=>
{
return
keyPath
.
split
(
'
.
'
).
reduce
((
prev
,
curr
)
=>
prev
[
curr
],
obj
);
};
let
value
=
getPropByPath
(
props
.
modelValue
,
prop
);
// clear tips
tipMessage
({
prop
,
message
:
''
});
...
...
@@ -104,12 +111,25 @@ export const component = {
return
Promise
.
resolve
(
true
);
};
const
validate
=
()
=>
{
/**
* 校验
* @param customProp 指定校验,用于用户自定义场景时触发,例如 blur、change 事件
* @returns
*/
const
validate
=
(
customProp
:
string
=
''
)
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
let
task
=
findFormItem
(
slots
.
default
());
let
errors
=
task
.
map
((
item
)
=>
{
return
checkRule
(
item
);
if
(
customProp
)
{
if
(
customProp
==
item
.
prop
)
{
return
checkRule
(
item
);
}
else
{
return
Promise
.
resolve
(
true
);
}
}
else
{
return
checkRule
(
item
);
}
});
Promise
.
all
(
errors
).
then
((
errorRes
)
=>
{
...
...
src/packages/__VUE/form/demo.vue
浏览文件 @
95df5bf9
...
...
@@ -18,10 +18,37 @@
<nut-textarea
placeholder=
"请输入备注"
type=
"text"
/>
</nut-form-item>
</nut-form>
<h2>
动态表单
</h2>
<nut-form
:model-value=
"dynamicForm.state"
ref=
"dynamicRefForm"
>
<nut-form-item
label=
"姓名"
prop=
"name"
required
:rules=
"[
{ required: true, message: '请填写姓名' }]">
<input
class=
"nut-input-text"
v-model=
"dynamicForm.state.name"
placeholder=
"请输入姓名"
type=
"text"
/>
</nut-form-item>
<nut-form-item
:label=
"'联系方式' + index"
:prop=
"'tels.' + index + '.value'"
required
:rules=
"[
{ required: true, message: '请填写联系方式' + index }]"
:key="item.key"
v-for="(item, index) in dynamicForm.state.tels"
>
<input
class=
"nut-input-text"
v-model=
"item.value"
:placeholder=
"'请输入联系方式' + index"
type=
"text"
/>
</nut-form-item>
<nut-cell>
<nut-button
size=
"small"
style=
"margin-right: 10px"
@
click=
"dynamicForm.methods.add"
>
添加
</nut-button>
<nut-button
size=
"small"
style=
"margin-right: 10px"
@
click=
"dynamicForm.methods.remove"
>
删除
</nut-button>
<nut-button
type=
"primary"
size=
"small"
@
click=
"dynamicForm.methods.submit"
>
提交
</nut-button>
</nut-cell>
</nut-form>
<h2>
表单校验
</h2>
<nut-form
:model-value=
"formData"
ref=
"ruleForm"
>
<nut-form-item
label=
"姓名"
prop=
"name"
required
:rules=
"[
{ required: true, message: '请填写姓名' }]">
<input
class=
"nut-input-text"
v-model=
"formData.name"
placeholder=
"请输入姓名"
type=
"text"
/>
<input
class=
"nut-input-text"
@
blur=
"customBlurValidate('name')"
v-model=
"formData.name"
placeholder=
"请输入姓名,blur 事件校验"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"年龄"
...
...
@@ -130,6 +157,40 @@ export default createDemo({
tel
:
''
,
address
:
''
});
const
dynamicRefForm
=
ref
<
any
>
(
null
);
const
dynamicForm
=
{
state
:
reactive
({
name
:
''
,
tels
:
new
Array
({
key
:
1
,
value
:
''
})
}),
methods
:
{
submit
()
{
dynamicRefForm
.
value
.
validate
().
then
(({
valid
,
errors
}:
any
)
=>
{
if
(
valid
)
{
console
.
log
(
'
success
'
,
dynamicForm
);
}
else
{
console
.
log
(
'
error submit!!
'
,
errors
);
}
});
},
remove
()
{
dynamicForm
.
state
.
tels
.
splice
(
dynamicForm
.
state
.
tels
.
length
-
1
,
1
);
},
add
()
{
let
newIndex
=
dynamicForm
.
state
.
tels
.
length
;
dynamicForm
.
state
.
tels
.
push
({
key
:
Date
.
now
(),
value
:
''
});
}
}
};
const
validate
=
(
item
:
any
)
=>
{
console
.
log
(
item
);
};
...
...
@@ -213,6 +274,16 @@ export default createDemo({
const
reset
=
()
=>
{
ruleForm
.
value
.
reset
();
};
// 失去焦点校验
const
customBlurValidate
=
(
prop
:
string
)
=>
{
ruleForm
.
value
.
validate
(
prop
).
then
(({
valid
,
errors
}:
any
)
=>
{
if
(
valid
)
{
console
.
log
(
'
success
'
,
formData
);
}
else
{
console
.
log
(
'
error submit!!
'
,
errors
);
}
});
};
// 函数校验
const
customValidator
=
(
val
:
string
)
=>
/^
\d
+$/
.
test
(
val
);
// Promise 异步校验
...
...
@@ -225,7 +296,20 @@ export default createDemo({
},
1000
);
});
};
return
{
ruleForm
,
formData
,
validate
,
customValidator
,
asyncValidator
,
submit
,
reset
,
formData2
,
addressModule
};
return
{
ruleForm
,
formData
,
validate
,
customValidator
,
asyncValidator
,
customBlurValidate
,
submit
,
reset
,
formData2
,
addressModule
,
dynamicForm
,
dynamicRefForm
};
}
});
</
script
>
...
...
src/packages/__VUE/form/doc.md
浏览文件 @
95df5bf9
...
...
@@ -44,33 +44,98 @@ app.use(CellGroup);
</nut-form>
```
### 动态表单
```
html
<nut-form
:model-value=
"dynamicForm.state"
ref=
"dynamicRefForm"
>
<nut-form-item
label=
"姓名"
prop=
"name"
required
:rules=
"[{ required: true, message: '请填写姓名' }]"
>
<input
class=
"nut-input-text"
v-model=
"dynamicForm.state.name"
placeholder=
"请输入姓名"
type=
"text"
/>
</nut-form-item>
<nut-form-item
:label=
"'联系方式'+index"
:prop=
"'tels.' + index + '.value'"
required
:rules=
"[{ required: true, message: '请填写联系方式'+index }]"
:key=
"item.key"
v-for=
"(item,index) in dynamicForm.state.tels"
>
<input
class=
"nut-input-text"
v-model=
"item.value"
:placeholder=
"'请输入联系方式'+index"
type=
"text"
/>
</nut-form-item>
<nut-cell>
<nut-button
size=
"small"
style=
"margin-right: 10px"
@
click=
"dynamicForm.methods.add"
>
添加
</nut-button>
<nut-button
size=
"small"
style=
"margin-right: 10px"
@
click=
"dynamicForm.methods.remove"
>
删除
</nut-button>
<nut-button
type=
"primary"
size=
"small"
@
click=
"dynamicForm.methods.submit"
>
提交
</nut-button>
</nut-cell>
</nut-form>
```
```
javascript
setup
(){
const
dynamicRefForm
=
ref
<
any
>
(
null
);
const
dynamicForm
=
{
state
:
reactive
({
name
:
''
,
tels
:
new
Array
({
key
:
1
,
value
:
''
})
}),
methods
:
{
submit
()
{
dynamicRefForm
.
value
.
validate
().
then
(({
valid
,
errors
}:
any
)
=>
{
if
(
valid
)
{
console
.
log
(
'
success
'
,
dynamicForm
);
}
else
{
console
.
log
(
'
error submit!!
'
,
errors
);
}
});
},
remove
()
{
dynamicForm
.
state
.
tels
.
splice
(
dynamicForm
.
state
.
tels
.
length
-
1
,
1
);
},
add
()
{
let
newIndex
=
dynamicForm
.
state
.
tels
.
length
;
dynamicForm
.
state
.
tels
.
push
({
key
:
Date
.
now
(),
value
:
''
});
}
}
};
return
{
dynamicForm
,
dynamicRefForm
};
}
```
### 表单校验
```
html
<nut-form
:model-value=
"formData"
ref=
"ruleForm"
>
<nut-form-item
label=
"姓名"
prop=
"name"
required
:rules=
"[{ required: true, message: '请填写姓名' }]"
>
<input
class=
"nut-input-text"
v-model=
"formData.name"
placeholder=
"请输入姓名"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"年龄"
prop=
"age"
required
:rules=
"[
{ required: true, message: '请填写年龄' },
{ validator: customValidator, message: '必须输入数字' },
{ regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
<nut-form-item
label=
"姓名"
prop=
"name"
required
:rules=
"[{ required: true, message: '请填写姓名' }]"
>
<input
class=
"nut-input-text"
@
blur=
"customBlurValidate('name')"
v-model=
"formData.name"
placeholder=
"请输入姓名,blur 事件校验"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"年龄"
prop=
"age"
required
:rules=
"[
{ required: true, message: '请填写年龄' },
{ validator: customValidator, message: '必须输入数字' },
{ regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
]"
>
<input
class=
"nut-input-text"
v-model=
"formData.age"
placeholder=
"请输入年龄,必须数字且0-200区间"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"联系电话"
prop=
"tel"
required
:rules=
"[
{ required: true, message: '请填写联系电话' },
{ validator: asyncValidator, message: '电话格式不正确' }
<input
class=
"nut-input-text"
v-model=
"formData.age"
placeholder=
"请输入年龄,必须数字且0-200区间"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"联系电话"
prop=
"tel"
required
:rules=
"[
{ required: true, message: '请填写联系电话' },
{ validator: asyncValidator, message: '电话格式不正确' }
]"
>
<input
class=
"nut-input-text"
v-model=
"formData.tel"
placeholder=
"请输入联系电话,异步校验电话格式"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"地址"
prop=
"address"
required
:rules=
"[{ required: true, message: '请填写地址' }]"
>
<input
class=
"nut-input-text"
v-model=
"formData.address"
placeholder=
"请输入地址"
type=
"text"
/>
</nut-form-item>
<nut-cell>
<nut-button
type=
"primary"
size=
"small"
style=
"margin-right: 10px"
@
click=
"submit"
>
提交
</nut-button>
<nut-button
size=
"small"
@
click=
"reset"
>
重置提示状态
</nut-button>
</nut-cell>
<input
class=
"nut-input-text"
v-model=
"formData.tel"
placeholder=
"请输入联系电话,异步校验电话格式"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"地址"
prop=
"address"
required
:rules=
"[{ required: true, message: '请填写地址' }]"
>
<input
class=
"nut-input-text"
v-model=
"formData.address"
placeholder=
"请输入地址"
type=
"text"
/>
</nut-form-item>
<nut-cell>
<nut-button
type=
"primary"
size=
"small"
style=
"margin-right: 10px"
@
click=
"submit"
>
提交
</nut-button>
<nut-button
size=
"small"
@
click=
"reset"
>
重置提示状态
</nut-button>
</nut-cell>
</nut-form>
```
```
javascript
...
...
@@ -98,6 +163,16 @@ setup(){
const
reset
=
()
=>
{
ruleForm
.
value
.
reset
();
};
// 失去焦点校验
const
customBlurValidate
=
(
prop
:
string
)
=>
{
ruleForm
.
value
.
validate
(
prop
).
then
(({
valid
,
errors
}:
any
)
=>
{
if
(
valid
)
{
console
.
log
(
'
success
'
,
formData
);
}
else
{
console
.
log
(
'
error submit!!
'
,
errors
);
}
});
};
// 函数校验
const
customValidator
=
(
val
:
string
)
=>
/^
\d
+$/
.
test
(
val
);
// Promise 异步校验
...
...
@@ -110,7 +185,7 @@ setup(){
},
1000
);
});
};
return
{
ruleForm
,
formData
,
validate
,
customValidator
,
asyncValidator
,
submit
,
reset
,
formData2
,
addressModule
};
return
{
ruleForm
,
formData
,
validate
,
customValidator
,
asyncValidator
,
customBlurValidate
,
submit
,
reset
};
}
```
...
...
@@ -240,15 +315,16 @@ setup(){
### FormItem Props
| 参数 | 说明 | 类型 | 默认值 |
|---------------------|--------------------------------------------------|------------------|---------|
| required | 是否显示必填字段的标签旁边的红色星号 | boolean |
`false`
|
| label-width | 表单项 label 宽度,默认单位为
`px`
| number
\|
string |
`90px`
|
| label-align | 表单项 label 对齐方式,可选值为
`center`
`right`
| string |
`left`
|
| body-align | 输入框对齐方式,可选值为
`center`
`right`
| string |
`left`
|
| error-message-align | 错误提示文案对齐方式,可选值为
`center`
`right`
| string |
`left`
|
| show-error-line | 是否在校验不通过时标红输入框 | boolean |
`true`
|
| show-error-message | 是否在校验不通过时在输入框下方展示错误提示 | boolean |
`true`
|
| 参数 | 说明 | 类型 | 默认值 |
|---------------------|------------------------------------------------------------------|------------------|---------|
| required | 是否显示必填字段的标签旁边的红色星号 | boolean |
`false`
|
| prop | 表单域 v-model 字段, 在使用表单校验功能的情况下,该属性是必填的 | string | - |
| label-width | 表单项 label 宽度,默认单位为
`px`
| number
\|
string |
`90px`
|
| label-align | 表单项 label 对齐方式,可选值为
`center`
`right`
| string |
`left`
|
| body-align | 输入框对齐方式,可选值为
`center`
`right`
| string |
`left`
|
| error-message-align | 错误提示文案对齐方式,可选值为
`center`
`right`
| string |
`left`
|
| show-error-line | 是否在校验不通过时标红输入框 | boolean |
`true`
|
| show-error-message | 是否在校验不通过时在输入框下方展示错误提示 | boolean |
`true`
|
### FormItem Rule 数据结构
...
...
@@ -265,7 +341,8 @@ setup(){
通过
[
ref
](
https://v3.cn.vuejs.org/api/special-attributes.html#ref
)
可以获取到 Form 实例并调用实例方法
| 方法名 | 说明 | 参数 | 返回值 |
|--------|------------------------|------|---------|
| submit | 提交表单进行校验的方法 | - | Promise |
| reset | 清空校验结果 | - | - |
\ No newline at end of file
| 方法名 | 说明 | 参数 | 返回值 |
|-------------------|--------------------------------------------------------------------|---------------------|---------|
| submit | 提交表单进行校验的方法 | - | Promise |
| reset | 清空校验结果 | - | - |
| validate
`v3.1.13`
| 用户主动触发校验,用于用户自定义场景时触发,例如 blur、change 事件 | 同 FormItem prop 值 | - |
\ No newline at end of file
src/packages/__VUE/formitem/index.scss
浏览文件 @
95df5bf9
...
...
@@ -25,7 +25,7 @@
font-weight
:
normal
;
width
:
90px
;
margin-right
:
10px
;
flex
:
none
;
flex
:
none
!
important
;
display
:
inline-block
;
word-wrap
:
break-word
;
&
.required
{
...
...
src/packages/__VUE/table/common.ts
浏览文件 @
95df5bf9
...
...
@@ -34,7 +34,7 @@ export const component = (componentName: string) => {
}
},
emits
:
[
'
sorter
'
],
setup
(
props
,
{
emit
,
slots
}
)
{
setup
(
props
:
any
,
{
emit
,
slots
}:
any
)
{
const
state
=
reactive
({
curData
:
props
.
data
});
...
...
src/sites/mobile-taro/vue/src/dentry/pages/form/index.vue
浏览文件 @
95df5bf9
...
...
@@ -18,10 +18,37 @@
<nut-textarea
placeholder=
"请输入备注"
type=
"text"
/>
</nut-form-item>
</nut-form>
<h2>
动态表单
</h2>
<nut-form
:model-value=
"dynamicForm.state"
ref=
"dynamicRefForm"
>
<nut-form-item
label=
"姓名"
prop=
"name"
required
:rules=
"[
{ required: true, message: '请填写姓名' }]">
<input
class=
"nut-input-text"
v-model=
"dynamicForm.state.name"
placeholder=
"请输入姓名"
type=
"text"
/>
</nut-form-item>
<nut-form-item
:label=
"'联系方式' + index"
:prop=
"'tels.' + index + '.value'"
required
:rules=
"[
{ required: true, message: '请填写联系方式' + index }]"
:key="item.key"
v-for="(item, index) in dynamicForm.state.tels"
>
<input
class=
"nut-input-text"
v-model=
"item.value"
:placeholder=
"'请输入联系方式' + index"
type=
"text"
/>
</nut-form-item>
<nut-cell>
<nut-button
size=
"small"
style=
"margin-right: 10px"
@
click=
"dynamicForm.methods.add"
>
添加
</nut-button>
<nut-button
size=
"small"
style=
"margin-right: 10px"
@
click=
"dynamicForm.methods.remove"
>
删除
</nut-button>
<nut-button
type=
"primary"
size=
"small"
@
click=
"dynamicForm.methods.submit"
>
提交
</nut-button>
</nut-cell>
</nut-form>
<h2>
表单校验
</h2>
<nut-form
:model-value=
"formData"
ref=
"ruleForm"
>
<nut-form-item
label=
"姓名"
prop=
"name"
required
:rules=
"[
{ required: true, message: '请填写姓名' }]">
<input
class=
"nut-input-text"
v-model=
"formData.name"
placeholder=
"请输入姓名"
type=
"text"
/>
<input
class=
"nut-input-text"
@
blur=
"customBlurValidate('name')"
v-model=
"formData.name"
placeholder=
"请输入姓名,blur 事件校验"
type=
"text"
/>
</nut-form-item>
<nut-form-item
label=
"年龄"
...
...
@@ -127,6 +154,40 @@ export default {
tel
:
''
,
address
:
''
});
const
dynamicRefForm
=
ref
<
any
>
(
null
);
const
dynamicForm
=
{
state
:
reactive
({
name
:
''
,
tels
:
new
Array
({
key
:
1
,
value
:
''
})
}),
methods
:
{
submit
()
{
dynamicRefForm
.
value
.
validate
().
then
(({
valid
,
errors
}:
any
)
=>
{
if
(
valid
)
{
console
.
log
(
'
success
'
,
dynamicForm
);
}
else
{
console
.
log
(
'
error submit!!
'
,
errors
);
}
});
},
remove
()
{
dynamicForm
.
state
.
tels
.
splice
(
dynamicForm
.
state
.
tels
.
length
-
1
,
1
);
},
add
()
{
let
newIndex
=
dynamicForm
.
state
.
tels
.
length
;
dynamicForm
.
state
.
tels
.
push
({
key
:
Date
.
now
(),
value
:
''
});
}
}
};
const
validate
=
(
item
:
any
)
=>
{
console
.
log
(
item
);
};
...
...
@@ -210,6 +271,16 @@ export default {
const
reset
=
()
=>
{
ruleForm
.
value
.
reset
();
};
// 失去焦点校验
const
customBlurValidate
=
(
prop
:
string
)
=>
{
ruleForm
.
value
.
validate
(
prop
).
then
(({
valid
,
errors
}:
any
)
=>
{
if
(
valid
)
{
console
.
log
(
'
success
'
,
formData
);
}
else
{
console
.
log
(
'
error submit!!
'
,
errors
);
}
});
};
// 函数校验
const
customValidator
=
(
val
:
string
)
=>
/^
\d
+$/
.
test
(
val
);
// Promise 异步校验
...
...
@@ -222,7 +293,20 @@ export default {
},
1000
);
});
};
return
{
ruleForm
,
formData
,
validate
,
customValidator
,
asyncValidator
,
submit
,
reset
,
formData2
,
addressModule
};
return
{
ruleForm
,
formData
,
validate
,
customValidator
,
asyncValidator
,
customBlurValidate
,
submit
,
reset
,
formData2
,
addressModule
,
dynamicForm
,
dynamicRefForm
};
}
};
</
script
>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录