效果:
文档:VeeValidate 支持vue3.0
第一步:安装
-
执行命令 npm i vee-validate@4.0.3
第二步:导入
-
修改文件 src/views/login/index.vue,哪个页面使用表单验证就导入以下的信息进行注册使用
import { Form, Field } from 'vee-validate'
components:{Form, Field}
第三步:将form表单部分的div换成Form,input需要校验的input标签改为Field
注意:Field标签必须使用name属性 :rules=""自定义的表单验证的方法 v-model="form."表单校验必须使用的
<Form class="form" v-slot='{ errors }'> // v-slot是作用域插槽用于展示错误的信息
<template v-if="!isMsgLogin">
<div class="form-item">
<div class="input">
<i class="iconfont icon-user"></i>
<Field autocomplete='off' type="text" name='account' :rules="checkUname" placeholder="请输入用户名或手机号" />
</div>
<div class="error" v-if='errors.account'><i class="iconfont icon-warning" />{{errors.account}}</div>
</div>
<template/>
</Form>
注意:errors.account中的account跟你写的name名字有关系
第四步:校验自定义组件XtxCheckbox(as属性可以指定为其他标签,也可以指定为组件,组件需要支持v-model否则校验不会触发)
-<XtxCheckbox v-model="form.isAgree" />
+<Field as='XtxCheckbox' name='isAgree' :rules='schema.isAgree' v-model="form.isAgree" />
第五步: 清空切换手机号注册或者二维码注册的表单验证与重置错误信息
// 表单数据
const form = reactive({
// 用户名
account: null,
// 密码
password: null,
// 手机号
mobile: null,
// 验证码
code: null,
// 是否同意
isAgree: false
})
// 登录方式的切换
const target = ref(null)
const changeLogin = type => {
isMsgLogin.value = type
// 清空表单:重置错误信息
for (const key in form) {
if (key === 'isAgree') {
form[key] = false
} else {
form[key] = null
}
}
// resetForm可以重置表单的错误信息,但是不能重置表单验证
target.value.resetForm()
全部代码:(Login-form单独组件部分)
<template>
<div class="account-box">
<div class="toggle">
<a @click="changeLogin(false)" href="javascript:;" v-if="isMsgLogin">
<i class="iconfont icon-user"></i> 使用账号登录
</a>
<a @click="changeLogin(true)" href="javascript:;" v-else> <i class="iconfont icon-msg"></i> 使用短信登录 </a>
</div>
<Form class="form" v-slot="{ errors }" ref="target">
<template v-if="!isMsgLogin">
<div class="form-item">
<div class="input">
<i class="iconfont icon-user"></i>
<Field
type="text"
placeholder="请输入用户名或手机号"
name="account"
autocomplete="off"
:rules="schema.account"
v-model="form.account"
/>
</div>
<!-- 错误提示 -->
<div class="error" v-if="errors.account"><i class="iconfont icon-warning" />{{ errors.account }}</div>
</div>
<div class="form-item">
<div class="input">
<i class="iconfont icon-lock"></i>
<Field
type="password"
v-model="form.password"
placeholder="请输入密码"
name="password"
:rules="schema.password"
/>
</div>
<!-- 错误提示 -->
<div class="error" v-if="errors.password"><i class="iconfont icon-warning" />{{ errors.password }}</div>
</div>
</template>
<template v-else>
<div class="form-item">
<div class="input">
<i class="iconfont icon-user"></i>
<Field type="text" name="mobile" :rules="schema.mobile" placeholder="请输入手机号" v-model="form.mobile" />
</div>
<!-- 错误提示 -->
<div class="error" v-if="errors.mobile"><i class="iconfont icon-warning" />{{ errors.mobile }}</div>
</div>
<div class="form-item">
<div class="input">
<i class="iconfont icon-code"></i>
<Field type="password" name="code" :rules="schema.code" placeholder="请输入验证码" v-model="form.code" />
<span class="code">发送验证码</span>
</div>
<!-- 错误提示 -->
<div class="error" v-if="errors.code"><i class="iconfont icon-warning" />{{ errors.code }}</div>
</div>
</template>
<div class="form-item">
<div class="agree">
<!-- <XtxCheckbox v-model="form.isAgree" /> -->
<!-- as表示field组件嘴周渲染成Xtxcheckboxzujian -->
<Field as="XtxCheckbox" v-model="form.isAgree" name="isAgree" :rules="schema.isAgree" />
<span>我已同意</span>
<a href="javascript:;">《隐私条款》</a>
<span>和</span>
<a href="javascript:;">《服务条款》</a>
</div>
<div class="error" v-if="errors.isAgree"><i class="iconfont icon-warning" />{{ errors.isAgree }}</div>
</div>
<a href="javascript:;" class="btn" @click="handlerLogin">登录</a>
</Form>
<div class="action">
<img src="https://qzonestyle.gtimg.cn/qzone/vas/opensns/res/img/Connect_logo_7.png" alt="" />
<div class="url">
<a href="javascript:;">忘记密码</a>
<a href="javascript:;">免费注册</a>
</div>
</div>
</div>
</template>
<script>
import { ref, reactive, getCurrentInstance } from 'vue'
// import Message from '@/components/library/Message'
// 专门做表单验证的,然后需要导入使用
import { Form, Field } from 'vee-validate'
import schema from '@/utils/vee-validate-schema.js'
export default {
name: 'LoginForm',
components: { Form, Field },
setup() {
const isMsgLogin = ref(true)
// const form = reactive({
// isAgree: false
// })
// 表单数据
const form = reactive({
// 用户名
account: null,
// 密码
password: null,
// 手机号
mobile: null,
// 验证码
code: null,
// 是否同意
isAgree: false
})
// 表单验证测试
// const checkUname = value => {
// if (!value) {
// return '请输入户名!'
// }
// return true
// }
// 登录方式的切换
const target = ref(null)
const changeLogin = type => {
isMsgLogin.value = type
// 清空表单:重置错误信息
for (const key in form) {
if (key === 'isAgree') {
form[key] = false
} else {
form[key] = null
}
}
// resetForm可以重置表单的错误信息,但是不能重置表单验证
target.value.resetForm()
}
// 登录
const instance = getCurrentInstance()
const handlerLogin = async () => {
const valid = await target.value.validate()
console.log(valid)
if (valid) {
// 调用接口实现登录
// Message({ text: '登录成功呀', type: 'success' })
instance.proxy.$message({ text: '登录成功呀', type: 'success' })
} else {
}
}
return { isMsgLogin, form, schema, changeLogin, target, handlerLogin }
}
}
</script>
<style lang="less" scoped>
// 账号容器
.account-box {
.toggle {
padding: 15px 40px;
text-align: right;
a {
color: @xtxColor;
i {
font-size: 14px;
}
}
}
.form {
padding: 0 40px;
&-item {
margin-bottom: 28px;
.input {
position: relative;
height: 36px;
> i {
width: 34px;
height: 34px;
background: #cfcdcd;
color: #fff;
position: absolute;
left: 1px;
top: 1px;
text-align: center;
line-height: 34px;
font-size: 18px;
}
input {
padding-left: 44px;
border: 1px solid #cfcdcd;
height: 36px;
line-height: 36px;
width: 100%;
&.error {
border-color: @priceColor;
}
&.active,
&:focus {
border-color: @xtxColor;
}
}
.code {
position: absolute;
right: 1px;
top: 1px;
text-align: center;
line-height: 34px;
font-size: 14px;
background: #f5f5f5;
color: #666;
width: 90px;
height: 34px;
cursor: pointer;
}
}
> .error {
position: absolute;
font-size: 12px;
line-height: 28px;
color: @priceColor;
i {
font-size: 14px;
margin-right: 2px;
}
}
}
.agree {
a {
color: #069;
}
}
.btn {
display: block;
width: 100%;
height: 40px;
color: #fff;
text-align: center;
line-height: 40px;
background: @xtxColor;
&.disabled {
background: #cfcdcd;
}
}
}
.action {
padding: 20px 40px;
display: flex;
justify-content: space-between;
align-items: center;
.url {
a {
color: #999;
margin-left: 10px;
}
}
}
}
</style>