如果问一个前端开发人员,表单操作的最后一步是什么?
他可能会说,是对表单的输入值做有效校验。要我说,这还不是最后一步。不知道你有没有遇到这样的需求,当我们提交表单之前,会请求接口做出一些判断,然后会补充一些表单信息再提交,这时候的交互可能是这样子的:弹出一个确认窗口,并携带一个子表单,需要用户做出一些选择后再进行按钮的提交或者取消操作。
这个时候我们可以使用 Message Box 消息弹出框组件
ElMessageBox.prompt('请输入内容', 'Tip', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^.+$/,
inputErrorMessage: '输入内容不能为空',
})
.then(({ value }) => {
ElMessage({
type: 'success',
message: `输入的内容为:${value}`,
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消输入',
})
})
但是如果我们需要的不是一个输入框,而是一个 select
组件或者 radio
switch
组件的话,怎么办?Element ElMessageBox.prompt 组件只提供了 输入内容的功能。
这里我们可以使用它 VNode 的功能,message 属性不仅支持传入字符串,还可以是 VNode 。借助 Vue 的 h
函数,实现插入任意组件的功能。
对于表单的选择,我们可以使用 ElSwitch
组件
ElMessageBox({
title: "提示",
message: () =>
h("div", {}, [
h(
"p",
{ style: { "margin-bottom": "10px" } },
"选择导出数据类型,默认只导出当前页的表格数据"
),
h(ElSwitch, {
modelValue: checked.value,
activeText: "全部",
activeValue: true,
inactiveText: "当前页",
inactiveValue: false,
"onUpdate:modelValue": (val: boolean) => {
checked.value = val;
}
})
])
})
.then(async () => {
if (checked.value) {
// todo
}
})
.catch(() => {
// todo
});
对于下拉选项我们使用 ElSelect 组件,然后子组件传入由多个选项 ElOption
组成的数组。
let childEles = [];
const { Code, Data } = await getPrdLineInfo();
if (Code === 0 && Data.length) {
childEles = Data.map(el => {
if (el.IsSelected) {
formData.value.ProductLineId = el.PrdLineId;
}
return h(ElOption, {
value: el.PrdLineId,
label: el.PrdLineName
});
});
}
ElMessageBox({
title: "提示",
showCancelButton: true,
message: () =>
h("div", [
h(
"p",
{ style: { "margin-bottom": "10px" } },
message + ",确定要提交数据吗?"
),
h("p", { style: { "margin-bottom": "5px" } }, "选择产品线"),
h(
ElSelect,
{
modelValue: formData.value.ProductLineId,
"onUpdate:modelValue": (val: string) => {
formData.value.ProductLineId = val;
},
style: { width: "100%" }
},
() => childEles
)
])
})
.then(async () => {
// todo
})
.catch(() => {
// todo
});
有了 VNode 支持就自由多了,我们就可以在表单提交前的确认弹窗里做很多事,表单提交意味着数据将要传到服务端,不能不谨慎。