石狮网站建设科技,容桂做pc端网站,汽车网站和移动端建设方案,p2p网站建设规划文章目录05-登录-表单校验06-登录-消息提示组件封装07-登录-账户登录08-登录-手机号登录09-退出登录05-登录-表单校验 文档#xff1a;https://vee-validate.logaretm.com/v4/ 支持vue3.0 第一步#xff1a;安装
执行命令 npm i vee-validate4.0.3
第二步#xff1a;导入 …
文章目录05-登录-表单校验06-登录-消息提示组件封装07-登录-账户登录08-登录-手机号登录09-退出登录05-登录-表单校验 文档https://vee-validate.logaretm.com/v4/ 支持vue3.0 第一步安装
执行命令 npm i vee-validate4.0.3
第二步导入
修改文件 src/views/login/index.vue
import { Form, Field } from vee-validate第三步定义校验规则
新建文件 src/utils/vee-validate-schema.js
// 定义校验规则提供给vee-validate组件使用
export default {// 校验accountaccount (value) {// value是将来使用该规则的表单元素的值// 1. 必填// 2. 6-20个字符需要以字母开头// 如何反馈校验成功还是失败返回true才是成功其他情况失败返回失败原因。if (!value) return 请输入用户名if (!/^[a-zA-Z]\w{5,19}$/.test(value)) return 字母开头且6-20个字符return true},password (value) {if (!value) return 请输入密码if (!/^\w{6,24}$/.test(value)) return 密码是6-24个字符return true},mobile (value) {if (!value) return 请输入手机号if (!/^1[3-9]\d{9}$/.test(value)) return 手机号格式错误return true},code (value) {if (!value) return 请输入验证码if (!/^\d{6}$/.test(value)) return 验证码是6个数字return true},isAgree (value) {if (!value) return 请勾选同意用户协议return true}
}提取目的 这些校验规则将来在其他表单验证时候可复用
第三步使用 Form 组件使用 vee-validate-schema 校验规则
修改文件 src/views/login/index.vue
-div classform.../div
Form classform :validation-schemaschema autocompleteoff.../Formimport veeSchema from /utils/vee-validate-schemasetup () {// 控制短信登录切换的const isMsgLogin ref(false)// 表单对象数据const form reactive({isAgree: true,account: null,password: null,mobile: null,code: null})// 校验规则对象const mySchema {account: schema.account,password: schema.password,mobile: schema.mobile,code: schema.code,isAgree: schema.isAgree}return { isMsgLogin, form, scheam:mySchema, submit }} 第四步使用 Field 组件添加表单项目校验
修改文件 src/views/login/index.vue div classform-itemdiv classinputi classiconfont icon-user/iField :class{error:errors.mobile} v-modelform.mobile namemobile typetext placeholder请输入手机号 //divdiv classerror v-iferrors.mobilei classiconfont icon-warning /{{errors.mobile}}/div/divdiv classform-item v-if!isMsgLogindiv classinputi classiconfont icon-lock/iField :class{error:errors.password} v-modelform.password namepassword typepassword placeholder请输入密码 //divdiv classerror v-iferrors.passwordi classiconfont icon-warning /{{errors.password}}/div/divdiv classform-item v-elsediv classinputi classiconfont icon-code/iField :class{error:errors.code} v-modelform.code namecode typepassword placeholder请输入验证码 /span classcode发送验证码/span/divdiv classerror v-iferrors.codei classiconfont icon-warning /{{errors.code}}/div/divForm classform :validation-schemaschema v-slot{errors} 其实就是把input改成 Field 组件默认解析成inputField 添加name属性作用是指定使用schema中哪个校验规则Form 添加 v-slot{errors} 使用作用域插槽暴露 errors 错误对象 通过 errors[校验规则名称] 取出错误信息有则显示无即隐藏
第五步如何校验 自定义组件 XtxCheckbox
修改文件 src/views/login/index.vue
-XtxCheckbox v-modelform.isAgree /
Field asXtxCheckbox nameisAgree v-modelform.isAgree/Field 的 as 属性可以指定为其他标签也可指定为组件。 但是组件需要支持 v-model 否则校验不会触发。
第六步如何在切换 短信 与 账户 登录时候清空表单和校验结果
修改文件 src/views/login/index.vue
Form refformCom classform :validation-schemaschema v-slot{errors} // 切换表单元素还原数据和清除校验效果const formCom ref(null)watch(isMsgLogin, () {// 还原数据form.isAgree trueform.account nullform.password nullform.mobile nullform.code null// 补充校验效果清除Form组件提供resetForm()formCom.value.resetForm()})首先需要自己手动清除数据然后使用Form 组件提供 resetForm 方法对表单进行清除校验结果
第七步如何整体表单校验
修改文件 src/views/login/index.vue
a clicklogin() hrefjavascript:; classbtn登 录/a// 需要在点击登录的时候对整体表单进行校验const login async () {// Form组件提供了一个 validate 函数作为整体表单校验当是返回的是一个promiseconst valid await formCom.value.validate()console.log(valid)}return { isMsgLogin, form, schema: mySchema, formCom, login }Form 组件提供 validate 方法对表单进行整体校验
06-登录-消息提示组件封装 目的在接口请求报错的时候给用户进行提示 组件功能分析
固定顶部显示有三种类型成功错误警告。显示消息提示时需要动画从上滑入且淡出。组件使用的方式不够便利封装成工具函数方式。
大致实现步骤 先把布局和三种情况的显示完成。 定义组件src/components/library/xtx-message.vue
templatediv classxtx-message :stylestyle[type]!-- 上面绑定的是样式 --!-- 不同提示图标会变 --i classiconfont :class[style[type].icon]/ispan classtext{{text}}/span/div
/template
script
export default {name: XtxMessage,props: {text: {type: String,default: },type: {type: String,// warn 警告 error 错误 success 成功default: warn}},setup () {// 定义一个对象包含三种情况的样式对象key就是类型字符串const style {warn: {icon: icon-warning,color: #E6A23C,backgroundColor: rgb(253, 246, 236),borderColor: rgb(250, 236, 216)},error: {icon: icon-shanchu,color: #F56C6C,backgroundColor: rgb(254, 240, 240),borderColor: rgb(253, 226, 226)},success: {icon: icon-queren2,color: #67C23A,backgroundColor: rgb(240, 249, 235),borderColor: rgb(225, 243, 216)}}return { style }}
}
/script
style scoped langless
.xtx-message {width: 300px;height: 50px;position: fixed;z-index: 9999;left: 50%;margin-left: -150px;top: 25px;line-height: 50px;padding: 0 25px;border: 1px solid #e4e4e4;background: #f5f5f5;color: #999;border-radius: 4px;i {margin-right: 4px;vertical-align: middle;}.text {vertical-align: middle;}
}
/style使用组件
XtxMessage text手机号或密码错误 typeerror /实现显示的时候动画效果
templateTransition namedowndiv classxtx-message :stylestyle v-showshow!-- 上面绑定的是样式 --!-- 不同提示图标会变 --i classiconfont :class[style[type].icon]/ispan classtext{{text}}/span/div/Transition
/templatescript
import { onMounted, ref } from vue
export default {name: XtxMessage,props: {text: {type: String,default: },type: {type: String,// warn 警告 error 错误 success 成功default: warn}},setup () {// 定义一个对象包含三种情况的样式对象key就是类型字符串const style {warn: {icon: icon-warning,color: #E6A23C,backgroundColor: rgb(253, 246, 236),borderColor: rgb(250, 236, 216)},error: {icon: icon-shanchu,color: #F56C6C,backgroundColor: rgb(254, 240, 240),borderColor: rgb(253, 226, 226)},success: {icon: icon-queren2,color: #67C23A,backgroundColor: rgb(240, 249, 235),borderColor: rgb(225, 243, 216)}}// 定义一个数据控制显示隐藏默认是隐藏组件挂载完毕显示const visible ref(false)onMounted(() {visible.value true})return { style, visible }}
}
/scriptstyle scoped langless
.down {-enter {-from {transform: translate3d(0,-75px,0);opacity: 0;}-active {transition: all 0.5s;}-to {transform: none;opacity: 1;}}
}
// 。。。 省略封装成vue实例函数式调用 vue3.0使用app.config.globalProperties挂载原型方法也支持直接导入函数使用
src/components/library/Message.js
// 实现使用函数调用xtx-message组件的逻辑
import { createVNode, render } from vue
import XtxMessage from ./xtx-message.vue// 准备dom容器
const div document.createElement(div)
div.setAttribute(class, xtx-message-container)
document.body.appendChild(div)
// 定时器标识
let timer nullexport default ({ type, text }) {// 实现根据xtx-message.vue渲染消息提示// 1. 导入组件// 2. 根据组件创建虚拟节点const vnode createVNode(XtxMessage, { type, text })// 3. 准备一个DOM容器// 4. 把虚拟节点渲染DOM容器中render(vnode, div)// 5. 开启定时移出DOM容器内容clearTimeout(timer)timer setTimeout(() {render(null, div)}, 3000)
}src/components/library/index.js
import Message from ./Message// 定义指令defineDirective(app) // 如果你想挂载全局的属性能够通过组件实例调用的属性 this.$messageapp.config.globalProperties.$message Message// 原型函数
}在登录逻辑中使用 src/views/login/index.vue
import Message from /components/library/Message// 帐号密码登录userAccountLogin(form).then(data {// 成功}).catch(e {// 失败Message({ type: error, text: 登录失败 })})07-登录-账户登录 目的完成以账户进行登录 定义API src/api/user.js
import request from /utils/request/*** 帐号登录* param {String} account - 用户名* param {String} password - 密码* returns Promise*/
export const userAccountLogin ({ account, password }) {return request(/login, post, { account, password })
}定义修改用户信息的 mutations src/store/module/user.js
// 用户状态
export default {namespaced: true,state: () ({id: ,account:,nickname: ,avatar: ,token: ,mobile: })
}进行登录 src/views/login/index.vue
import { userAccountLogin } from /api/user
import Message from /components/library/Message
import { useStore } from vuex
import { useRoute, useRouter } from vue-router// 使用storeconst store useStore()// 使用routerconst router useRouter()// 使用routeconst route useRoute()// 登录提交const submit async () {// 整体校验const valid await target.value.validate()console.log(valid)if (valid) {// 发送请求if (!isMsgLogin.value) {// 帐号密码登录userAccountLogin(form).then(data {// 成功// 1. 存储信息const { id, account, nickname, avatar, token, mobile } data.resultstore.commit(user/setUser, { id, account, nickname, avatar, token, mobile })// 2. 提示Message({ type: success, text: 登录成功 })// 3. 跳转router.push(route.query.redirectUrl || /)}).catch(e {// 失败Message({ type: error, text: e.response.data.message || 登录失败 })})} else {// 短信登录}}}08-登录-手机号登录 src/api/user.js实现代码 封装好发短信和进行短信登录的接口API
/*** 短信登录* param {String} mobile - 手机号* param {String} code - 验证码* returns Promise*/
export const userMobileLogin ({ mobile, code }) {return request(/login/code, post, { mobile, code })
}/*** 获取短信登录验证码* param {String} mobile - 手机号* returns Promise*/
export const userMobileLoginMsg (mobile) {return request(/login/code, get, { mobile })
}src/views/login/index.vue 实现代码发送短信
根据数据渲染按钮文字绑定点击事件发送验证码 span clicksend() classcode{{time0?发送验证码:${time}秒后发送}}/span使用 schma 函数来校验mobile如果成功继续执行不成功使用Form组件错误 setFieldError
发送验证码需要校验手机号和判断是否60秒内方可发送。组件销毁时候清除定时器。
import { useIntervalFn } from vueuse/core// pause 暂停 resume 开始// useIntervalFn(回调函数,执行间隔,是否立即开启)const time ref(0)const { pause, resume } useIntervalFn(() {time.value--if (time.value 0) {pause()}}, 1000, false)onUnmounted(() {pause()})// 发送短信const send async () {const valid mySchema.mobile(form.mobile)if (valid true) {// 通过if (time.value 0) {// 没有倒计时才可以发送await userMobileLoginMsg(form.mobile)Message({ type: success, text: 发送成功 })time.value 60resume()}} else {// 失败使用vee的错误函数显示错误信息 setFieldError(字段,错误信息)formCom.value.setFieldError(mobile, valid)}}return { isMsgLogin, form, schema: mySchema, formCom, login, send, time }src/views/login/index.vue 实现代码手机号登录 // 使用storeconst store useStore()// 使用routerconst router useRouter()// 使用routeconst route useRoute()// 登录提交const submit async () {// 整体校验const valid await target.value.validate()if (valid) {// 发送请求let data nulltry {if (!isMsgLogin.value) {// 帐号登录data await userAccountLogin(form)} else {// 短信登录// 1. 定义两个API 短信登录获取短信验证码// 2. 实现发送短信验证码发送功能// 3. 完成手机号短信验证码登录逻辑data await userMobileLogin(form)}} catch (e) {Message({ type: error, text: e.response.data.message || 登录失败 })}// 成功// 1. 存储信息const { id, account, nickname, avatar, token, mobile } data.resultstore.commit(user/setUser, { id, account, nickname, avatar, token, mobile })// 2. 提示Message({ type: success, text: 登录成功 })// 3. 跳转router.push(route.query.redirectUrl || /)}}09-退出登录 目的完成退出 src/components/app-topnav.vue template v-ifprofile.tokenlia hrefjavascript:;i classiconfont icon-user/i{{profile.account}}/a/lilia clicklogout() hrefjavascript:;退出登录/a/li/templateimport { computed } from vue
import { useStore } from vuex
import { useRouter } from vue-router
export default {name: AppTopnav,setup () {// 获取用户的登录信息才能控制切换导航菜单const store useStore()// 使用vuex中的state需要设置计算属性否则不是响应式const profile computed(() {return store.state.user.profile})const router userRouter()const logout () {store.commit(user/setUser,{})router.push(/login)}return { profile, logout}}
}