vue3表单组件的封装
本组件只简单封装了输入框的类型,其他类型可自行拓展~~ 效果图:
本项目依赖库:
bootstrap:样式库
mitt: vue3全局事件(相当于vue2的中央事件总线bus);
开始无脑撸代码~~~~~~~~
1、安装依赖
npm install bootstrap mitt -D
//bootstrap记得在main.ts中引入
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'
2、引入mitt(mitt具体用法参考上述mitt地址链接)
在util/hooks文件下新建mitt.ts文件
代码如下:
import mitt from "mitt";
export type Fun = () => Boolean;
type Events = {
listenSubmit: Fun;
bar?: number;
};
export const emitter = mitt<Events>();
3、表单验证规则
在util/hooks文件下新建common.ts文件
代码如下:
export interface ruleProp {
type: "required" | 'email' | 'phone' | 'rang',
message: string
}
export type rule = ruleProp[];
4、新建validate.vue组件
<template>
<div>
<form class="row">
<div class="col-3"></div>
<div class="mb-3 col-6">
<label for="validationServer05" class="form-label">{{ attrs.label }}</label>
<input v-bind="attrs" ref="ipt" @blur="changeValue" :value="iptRef.value" @input="getchangeValue"
class="form-control" :class="!isError ? 'is-invalid' : ''"
aria-describedby="validationServer05Feedback">
<div v-if="!isError" class="invalid-feedback">
{{ iptRef.message }}
</div>
</div>
</form>
</div>
</template>
<script lang='ts' setup>
import { PropType, defineProps, onMounted, reactive, ref, useAttrs } from 'vue';
import { rule } from "../util/hooks/common";
import { emitter } from "../util/hooks/mitt";
const attrs = useAttrs();
const prop = defineProps({
rules: Array as PropType<rule>,
modelValue: String,
})
const emit = defineEmits(["update:modelValue"]);
let reg = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/
const isError = ref<undefined | boolean>(true)
const iptRef = reactive({
value: prop.modelValue || "",
message: "",
});
const getchangeValue = (e: Event) => {
const val = (e.target as HTMLInputElement).value;
iptRef.value = val;
emit("update:modelValue", iptRef.value)
}
const changeValue = () => {
isError.value = true;
if (!prop.rules) return true;
let res = prop.rules.every((item) => {
let pass = false;
iptRef.message = item.message;
switch (item.type) {
case "required":
pass = (iptRef.value != "");
break;
case "email":
pass = (reg.test(iptRef.value));
break;
default:
pass = false
break;
}
return pass;
})
isError.value = res;
return res;
}
onMounted(() => {
emitter.emit("listenSubmit", changeValue)
})
</script>
<style scoped>
.mb {
margin-top: 20px;
}
</style>
5、新建form组件
<template>
<div>
<form class="form-content" onsubmit="return false">
<slot name="default"></slot>
<div class="form-submit" @click="handleSubmit">
<slot name="submit">
<button class="btn btn-primary">提交</button>
</slot>
</div>
</form>
</div>
</template>
<script lang='ts' setup>
import { defineEmits, onUnmounted, reactive, toRefs } from 'vue';
import { emitter, Fun } from "../util/hooks/mitt";
let iptArr: Fun[] = [];
const callBack = (params: Fun) => {
iptArr.push(params)
console.log(iptArr);
}
emitter.on("listenSubmit", callBack);
/* 组件销毁同时停止监听 */
onUnmounted(() => {
emitter.off("listenSubmit", () => { iptArr = [] })
})
const emits = defineEmits<{ (e: 'submitForm', params: boolean): void }>();
/* 表单提交 */
const handleSubmit = () => {
let res = iptArr.every(item => {
return item();
})
emits("submitForm", res)
}
</script>
<style scoped></style>
6、验证使用
<template>
<form-com @submitForm="submitForm">
<validate-com :rules="rules" placeholder="请输入账户" type="text" label="邮箱"
v-model="validateValue.emial"></validate-com>
<validate-com :rules="rulePassword" placeholder="请输入密码" type="password" label="密码" v-model="validateValue.password"></validate-com>
<template #submit>
<button class="btn btn-danger">提交表单</button>
</template>
</form-com>
<!-- <div>{{ validateValue }}</div> -->
</template>
<script lang='ts' setup>
import { reactive } from 'vue'
import validateCom from "../components/validate.vue"
import formCom from "../components/form.vue"
import { rule } from "../util/hooks/common";
let validateValue = reactive({
emial: "",
password: ""
})
/* 邮箱验证*/
const rules: rule = [{
type: "required",
message: "请输入文字"
}, {
type: "email",
message: "邮箱格式不正确"
}]
/* 密码验证 */
const rulePassword: rule = [{
type: "required",
message: "请输入密码"
}]
/* 获取表单数据 */
const submitForm = (val: boolean) => {
console.log("~~~~~表单提交结果", val);
if (val) {
alert("表单提交")
} else {
alert("表单未提交")
}
}
</script>
<style scoped></style>