首页 > 其他分享 >vue3项目-小兔鲜儿笔记-商品详情页03和登录页01

vue3项目-小兔鲜儿笔记-商品详情页03和登录页01

时间:2022-09-06 23:33:35浏览次数:71  
标签:03 account 01 return 鲜儿 校验 value 组件 const

1.封装数量选择组件

功能分析:

  1. 默认值为1

  2. 可限制最大最小值

  3. 点击-就是减1,点击+就是加1

  4. 需要完成v-model的双向数据绑定

  5. 存在无label的情况

<script setup>
// 组件间的v-model =》父组件绑定:modelValue,监听@update:modelValue
import { useVModel } from '@vueuse/core'

const emit = defineEmits(['update:modelValue', 'change'])
const props = defineProps({
  modelValue: {
    type: Number,
    default: 1
  },
  min: {
    type: Number,
    default: 1
  },
  max: {
    type: Number,
    default: 100
  },
  label: {
    type: String,
    default: ''
  }
})

// 使用useVModel做数据的双向绑定,这样修改值就会自动通知父组件
// 参数1为props,参数2为从父组件接收的参数,参数3是要发送的自定义事件
const count = useVModel(props, 'modelValue', emit)

// 修改值函数
const changeNum = (step) => {
  const newVal = count.value + step
  if (newVal < props.min || newVal > props.max) return
  // 修改count值就会自动通知父组件count值修改
  count.value = newVal
  // 同时发出change通知
  emit('change', count.value)
}
</script>

 

2.封装按钮组件

目的:封装一个通用按钮组件,有大、中、小、超小4种尺寸,有默认、主要、次要、灰色四种类型

<template>
  <button class="xtx-button" :class="[size, type]">
    <slot />
  </button>
</template>

<script setup>
defineProps({
  size: {
    type: String,
    default: 'middle'
  },
  type: {
    type: String,
    default: 'default'
  }
})
</script>
.large {
  width: 240px;
  height: 50px;
  font-size: 16px;
}
.middle {
  width: 180px;
  height: 50px;
  font-size: 16px;
}
.small {
  width: 100px;
  height: 32px;
  font-size: 14px;
}
.mini {
  width: 60px;
  height: 32px;
  font-size: 14px;
}

.default {
  border-color: #e4e4e4;
  color: #666;
}
.primary {
  border-color: @xtxColor;
  background-color: @xtxColor;
  color: #fff;
}
.plain {
  border-color: @xtxColor;
  color: @xtxColor;
  background-color: lighten(@xtxColor, 50%);
}
.gray {
  border-color: #ccc;
  background-color: #ccc;
  color: #fff;
}

 

3. 登录-表单校验

  1. 定义校验规则

    utils/vee-validate.js
    
    // 定义校验规则给vee-validate组件使用
    export default {
      // 校验account
      account(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
      }
    }
  2. 使用vee-validate提供的Form组件,绑定validation-schema为上述自定义校验规则
        <Form
            ref="formCom"
            class="form"
            :validation-schema="mySchema"
            autocomplete="off"
            v-slot="{errors}"
        >
                ....
  3.  使用vee-validate提供的Field组件代替input表单元素,指定name属性为自定义校验规则中的某项,比如,自定义校验中:account(){...},这里指定name就为account
                <Field
                    :class="{error: errors.account}"
                    v-model="form.account"
                    name="account"
                    type="text"
                    placeholder="请输入用户名或手机号"
                />
                        ....
  4. Form组件内部使用了默认插槽,这个插槽会返回errors错误对象,用于提示错误信息,比如errors.account就是显示自定义校验中account未通过校验返回的错误信息
              <div class="error" v-if="errors.account">
                <i class="iconfont icon-warning"></i>
                {{ errors.account }}
              </div>
                ...
  5. 切换组价时调用重置表单的方法清除校验结果
    const formCom = ref(null) // Form表单的ref对象
    
    // 表单数据
    const form = reactive({
      isAgree: true,
      account: null,
      password: null,
      mobile: null,
      code: null
    })
    // 表单校验规则
    const mySchema = {
      account: veeSchema.account,
      password: veeSchema.password,
      mobile: veeSchema.mobile,
      code: veeSchema.code,
      isAgree: veeSchema.isAgree
    }
    
    watch(isMsgLogin, () => {
      form.account = null
      form.code = null
      form.mobile = null
      form.isAgree = true
      form.password = null
      // formCom组件提供重置表单的方法resetForm()
      formCom.value.resetForm()
    })
  6. 当点击登录时,提交表单,调用Form组件的ref对象提供的统一校验方法validate()
    // 统一校验,Form组件提供统一校验方法validate()
    const login = async () => {
      const valid = await formCom.value.validate()
      if (valid) {
        // 账号登录
        if (!isMsgLogin.value) {
          try {
            const {result} = await userAccountLogin({account: form.account, password: form.password})
            const {id, avatar, nickname, account, mobile, token} = result
            // 1.获取用户信息并存储到userStore中
            userStore.setUser({
              id,
              avatar,
              nickname,
              account,
              mobile,
              token
            })
            // 2.消息提醒
            Message({type: 'success', text: '登录成功'})
            // 3.跳转
            await router.push(route.query.redirectUrl || '/')
          } catch (e) {
            Message({type: 'error', text: '登录失败'})
          }
        } else {
          // 手机号登录
          try {
            if (codeSpan.value.disabled) {
              const {result} = await userMobileLogin({mobile: form.mobile, code: form.code})
              const {id, avatar, nickname, account, mobile, token} = result
              // 1.获取用户信息并存储到userStore中
              userStore.setUser({
                id,
                avatar,
                nickname,
                account,
                mobile,
                token
              })
              // 2.消息提醒
              Message({type: 'success', text: '登录成功'})
              // 3.跳转
              await router.push(route.query.redirectUrl || '/')
            } else {
              throw Error('未发送验证码')
            }
          } catch (e) {
            Message({type: 'error', text: '登录失败'})
          }
        }
      }
    }

标签:03,account,01,return,鲜儿,校验,value,组件,const
From: https://www.cnblogs.com/jzhFlash/p/16663730.html

相关文章

  • 报错 drf TypeError: register() got an unexpected keyword argument 'basename'
    原因:drf<djangorestframework>版本问题转载自:  https://stackoverflow.com/questions/59733820/django-rest-framework-drf-typeerror-register-got-an-unexpec......
  • PAT Advanced 1031 Hello World for U(20)
    题目描述:GivenanystringofN(≥5)characters,youareaskedtoformthecharactersintotheshapeofU.Forexample,helloworldcanbeprintedas:hdel......
  • PAT Advanced 1032 Sharing(25)
    题目描述:TostoreEnglishwords,onemethodistouselinkedlistsandstoreawordletterbyletter.Tosavesomespace,wemayletthewordssharethesames......
  • mysqldump throws: Unknown table 'COLUMN_STATISTICS' in information_schema (1109)
    AWSRDS_MYSQL8.0执行mysqldump报以下错误mysqldumpthrows:Unknowntable'COLUMN_STATISTICS'ininformation_schema(1109) 具体$>mysqldump--single-tra......
  • GO语言自学_013_接口
    代码packagemainimport"fmt"/*go语言中,有专门的关键字表示接口:interfaceinterface不仅可以处理多态,还可以接收任意的数据类型。*/funcmain(){ //定义三个接......
  • 03-Nginx执行过程分析
    Nginx显示默认页面过程分析客户端在请求Nginx的时候会找到Nginx的路由表,然后查看映射也就是Nginx的配置文件#进入配置文件目录cdconf/#查看配置文件vinginx......
  • 01-Nginx领域概念
    什么是NginxNginx是一个高可用的HTTP和反向代理Web服务器,同时也提供IMAP/POP3/SMTP服务主要功能反向代理通过配置文件可以实现集群和负载均衡静态资源虚拟化常见......
  • 爬虫01
    爬虫通过编写程序来获取互联网资源需求:用程序模拟浏览器,输入一个网址,从该网址中获取到资源或者内容python搞定以上需求导包fromurllib.requestimporturlopen2.......
  • conda环境报错:libgomp.so.1: version `GOMP_4.0' not found?libstdc++.so.6: version `
    问题之前的conda环境好好地,最近不知为何被破坏了,运行即报错:/miniconda3/opt/lib/R/bin/exec/R:/miniconda3/opt/lib/R/bin/exec/../../lib/../../libgomp.so.1:version......
  • CF1325F Ehab's Last Theorem
    传送门思路dfs树的一道出色的应用题令\(k=\lceil\sqrtn\rceil\)我们先按照遍历的顺序构建出dfs树对于一条返祖边\((u,v)\),如果有\(dep_u-dep_v+1\gek\),......