Vite+Ts setup语法糖下表单验证

2,042 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

设计一个登录页面

本文初始代码是这个地址:juejin.cn/post/697210…
我采用的大部分代码来自于这个地址:juejin.cn/post/697246…
话不多说,show me the code,这里直接将login/index.vue覆盖如下

<template>
  <div class="login-wrapper">
    <div :class="['login-container', loginActive ? 'active' : '']">
      <div class="switch-wrapper row aCenter jCenter">
        <div class="btn-wrapper row aCenter jCenter">
          <div
            v-if="loginActive"
            class="txt row aCenter jCenter"
            @click="loginActive = !loginActive"
          >
            去注册
          </div>
          <div v-else class="txt row aCenter jCenter" @click="loginActive = !loginActive">
            去登录
          </div>
        </div>
      </div>
      <div :class="['outerBox', loginActive ? 'active' : '']">
        <div class="container row aCenter jCenter">
          <div class="login" v-show="loginActive">
            <el-form :model="loginModel" status-icon :rules="loginRules" ref="loginRef">
              <div class="title">登录</div>
              <el-form-item prop="username">
                <el-input
                  type="text"
                  placeholder="请输入账号 / 手机号 / 邮箱"
                  v-model="loginModel.username"
                />
              </el-form-item>
              <el-form-item prop="password">
                <el-input type="password" placeholder="请输入密码" v-model="loginModel.password" />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" class="btn-login" @click="handleLogin">登录</el-button>
              </el-form-item>
            </el-form>
          </div>
          <div class="register" v-show="!loginActive">
            <el-form :model="registerModel" status-icon :rules="registerRules" ref="registerRef">
              <div class="title">注册</div>
              <el-form-item prop="username">
                <el-input
                  type="text"
                  placeholder="请输入账号 / 手机号 / 邮箱"
                  v-model="registerModel.username"
                />
              </el-form-item>
              <el-form-item prop="email">
                <el-input type="text" placeholder="请输入邮箱地址" v-model="registerModel.email" />
              </el-form-item>
              <el-form-item prop="mobile">
                <el-input
                  placeholder="请输入手机号码"
                  v-model.number="registerModel.mobile"
                  style="width: 100%"
                />
              </el-form-item>
              <el-form-item prop="password">
                <el-input
                  type="password"
                  placeholder="请输入密码"
                  v-model="registerModel.password"
                />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" class="btn-login" @click="handleRegister">
                  确认注册
                </el-button>
              </el-form-item>
            </el-form>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue'
const loginActive = ref(false)
const loginModel = reactive({ username: undefined, password: undefined })
const registerModel = reactive({
  username: undefined,
  email: undefined,
  mobile: undefined,
  password: undefined
})
const checkEmail = (_rule: any, value: any, callback: any) => {
  if (!value) {
    callback('请输入邮箱')
  }
  if (!/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(value)) {
    callback(new Error('邮箱格式不正确'))
  } else {
    callback()
  }
}
const checkMobile = (_rule: any, value: any, callback: any) => {
  if (!value) {
    callback('请输入手机号')
  }
  if (!/^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/.test(value)) {
    callback(new Error('手机号格式不正确'))
  } else {
    callback()
  }
}
const loginRules = {
  username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
}
const registerRules = {
  username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
  mobile: [{ required: true, validator: checkMobile, trigger: 'blur' }],
  email: [{ required: true, validator: checkEmail, trigger: 'blur' }]
}
const loginRef = ref()
const registerRef = ref()
const handleLogin = () => {
  loginRef.value.validate((vaild) => {
    if (vaild) {
      console.log(1)
    }
  })
}
const handleRegister = () => {
  registerRef.value.validate((vaild) => {
    if (vaild) {
      console.log(123)
    }
  })
}
</script>
<style scoped>
.login-wrapper {
  background-color: #ededed;
  display: flex;
  width: 100vw;
  height: 100vh;
  margin: auto;
}
.login-container {
  background-color: #fff;
  position: relative;
  width: 1000px;
  height: 600px;
  margin: auto;
  overflow: hidden;
  border-radius: 5px;
  box-shadow: 0 0 10px 5px #ddd;
}
.switch-wrapper {
  position: absolute;
  z-index: 99;
  left: 0;
  overflow: hidden;
  width: 32%;
  height: 100%;
  transition: transform 1s ease-in-out;
}
.switch-wrapper::after {
  content: '';
  display: block;
  background-image: url('@/assets/login/login-bg.jpg');
  background-size: 1000px 550px;
  background-position: top left;
  width: 100%;
  height: 100%;
  overflow: hidden;
  transition: all 1s ease-in-out;
}
.active .switch-wrapper {
  transform: translateX(calc(1000px - 100%));
}
.active .switch-wrapper::after {
  background-position: top right;
}
.txt {
  width: 100%;
  height: 100%;
  transition: all 1s ease-in-out;
}
.top-wrapper {
  position: absolute;
  width: 260px;
  height: 168px;
  top: 50px;
  background-color: rgba(255, 255, 255, 0.7);
  padding: 10px;
  border-radius: 5px;
}
.btn-wrapper {
  position: absolute;
  width: 100px;
  height: 36px;
  color: #fffffe;
  background-color: #6689e2;
  font-size: 15px;
  border-radius: 30px;
  cursor: pointer;
  flex-wrap: wrap;
  overflow: hidden;
}
.outerBox {
  position: absolute;
  z-index: 3;
  left: 32%;
  overflow: hidden;
  width: 68%;
  height: 100%;
  transition: all 1s ease-in-out;
}
.container {
  width: 100%;
  height: 100%;
  background-color: #fffffe;
}
.active .outerBox {
  transform: translateX(calc(-1000px + 100%));
}
.ld {
  width: 200px;
  height: 40px;
  position: absolute;
  right: 16px;
  top: 16px;
}
.title {
  font-size: 36px;
  line-height: 1.5;
  text-align: center;
  margin-bottom: 30px;
  color: #666;
}
.btn-login {
  width: 100%;
}

.row {
  display: flex;
  display: -webkit-flex;
  flex-direction: row;
}
.column {
  display: flex;
  display: -webkit-flex;
  flex-direction: column;
}
.aCenter {
  align-items: center;
}
.jCenter {
  justify-content: center;
}
</style>

效果如下 登录效果 结合这个页面整理一下常用的Form表单验证和<script setup lang="ts"><>的写法

vue setup 语法糖总结

设置响应式数据

设置对象或者属性变为响应式的写法有两种:定义为ref(适用于单个属性),定义为reactive(适用于一个对象)。举个例子:假如说一个列表页面如果需要设置加载中,可以定义loading为ref,如果需要提交查询可以将查询条件封装为一个对象,然后定义为reactive,例如下边这些代码 定义响应式

提交Form表单

如果想要提交form表单数据,需要使用reactive先定义一个响应式对象,然后在对应的组件中使用V-model绑定对象。步骤如下

  • 定义响应式form表单对象 设置form step1
  • 初始化form并将响应式对象的属性使用v-model对应到组件上 设置form step2

Form表单数据验证

setup下基于确定好的规则验证form表单数据步骤可以分为以下几步

  • 定义一个响应式数据执行需要验证的表单,我一般使用ref const loginRef = ref()
  • 定义规则,如果是只需要验证是否需要输入,只需要定义required为true、message为提示信息、tigger为blur即可。如果需要使用添加自己的验证方法,去除message替换为validator然后指向自己的方法 定义规则
  • 定义form表单使用该规则
    使用规则
  • 提交时验证:在提交的方法里使用validate验证 提交时验证
    此处因为定义数据是ref,所以需要使用ref.value.validate,在里边判断是否验证通过,然后直接将form提交即可。这样就完成了在setup语法糖里验证表单的功能

结语

上一篇文章立下flag要写一个首页,但是在引入echarts时,使用require引入遇到了一些问题。下篇文章计划使用import按需引入echarts,计划明天出文档。 欢迎关注我的掘金账号:juejin.cn/user/261290…
欢迎star我的git项目:gitee.com/liangminghu…
下期预告:设计一个花里胡哨(不怎么好看)的首页和引入echarts时遇到的坑以及处理方法。