欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue?Validate表單組件的封裝詳解

 更新時(shí)間:2023年09月10日 11:42:21   作者:追夢(mèng)杰尼龜  
這篇文章主要為大家詳細(xì)介紹了Vue?Validate表單組件的封裝的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解下

之前一直是直接去使用別人現(xiàn)成的組件庫,也沒有具體去了解人家的組件是怎么封裝的,造輪子才會(huì)更好地提高自己,所以嘗試開始從封裝Form表單組件開始

一:組件需求分析

本次封裝組件,主要是摸索封裝組件的流程,對(duì)于具體需要的方法和屬性,只會(huì)實(shí)現(xiàn)其中部分方法和屬性,之后一點(diǎn)一點(diǎn)才進(jìn)行添加

表單項(xiàng)組件,ValidateInput組件的封裝

  • 根據(jù)傳遞不同的type類型有著不同的校驗(yàn)規(guī)則
  • 支持V-model,對(duì)于封裝的自定義組件支持v-model雙向綁定也是一個(gè)很關(guān)鍵的屬性
  • tag根節(jié)點(diǎn)的類型

form組件,提交事件

  • 驗(yàn)證整體表單項(xiàng),是否通過
  • 清空表單項(xiàng)的內(nèi)容

二:技術(shù)棧

Vue3

TS

Bootstrap樣式庫

三:封裝Validate-input驗(yàn)證表單項(xiàng)組件

思路

1. 明確屬性和事件

  • v-model屬性
  • rules屬性:根據(jù)不同type不同校驗(yàn)規(guī)則
  • tag根節(jié)點(diǎn)類型

ValidateInput組件

<template>
  <div class="validate-input-container pb-3">
    <input
      class="form-control"
      :class="{ 'is-invalid': inputRef.error }"
      :value="modelValue"
      @blur="validateInput"
      @input="updateValue"
      v-bind="$attrs"
    />
    <span v-if="inputRef.error" class="invalid-feedback">{{ inputRef.message }}</span>
  </div>
</template>
<script setup lang="ts">
//禁用 Attributes 繼承
defineOptions({
  inheritAttrs: false
})
//定義傳來的一個(gè)參數(shù)類型
interface RangeProp {
  message: string
  length: number
}
interface RuleProp {
  type: 'required' | 'email' | 'range'
  message?: string
  //至少位數(shù)
  min?: RangeProp
  max?: RangeProp
}
//數(shù)組類型
export type RulesProp = RuleProp[]
//接收參數(shù)
const props = defineProps<{
  rules?: RulesProp
  //自定義組件使用v-model需要用modelValue來接收參數(shù)
  modelValue: string
}>()
//定義表單的數(shù)據(jù)
const inputRef = reactive({
  //如果為空
  val: props.modelValue || '',
  error: false, //表單驗(yàn)證是否通過
  message: '' //錯(cuò)誤信息
})
</script>

禁用Attributes繼承:透傳 attribute”指的是傳遞給一個(gè)組件,卻沒有被該組件聲明為 props 或 emits 的 attribute 或者 v-on 事件監(jiān)聽器。最常見的例子就是 class style id 。

<!-- <MyButton> 的模板 -->
<button>click me</button>

當(dāng)父組件使用該組件,并且傳入class:

<MyButton class="large" />

最終會(huì)在根元素出現(xiàn)class=‘large“, <MyButton> 并沒有將 class 聲明為一個(gè)它所接受的 prop,所以 class 被視作透傳 attribute,自動(dòng)透傳到了 <MyButton> 的根元素上。

因此需要禁用Attibutes繼承

定義接收參數(shù)類型

  • rules可選參數(shù),接收數(shù)組
  • modelValue:接收字符串即輸入的值

2. v-model屬性

在使用一個(gè)自定義組件給其添加v-model屬性,其自定義組件內(nèi)部做了兩件事

將內(nèi)部原生的input元素的值綁定到組件內(nèi)部Prop屬性modelValue

當(dāng)原生input元素觸發(fā)時(shí)候,觸發(fā)一個(gè)攜帶了新值的 update:modelValue 自定義事件

          <!-- 自定義組件Validate-input -->
          <Validate-input v-model="loginParams.email" :rules="emailRules" placeholder="請(qǐng)輸入郵箱地址"></Validate-input>

Validate-input組件

//接收參數(shù)
const props = defineProps<{
  rules?: RulesProp
  //自定義組件使用v-model需要用modelValue來接收參數(shù)
  modelValue: string
}>()

props接收了,modelValue屬性,類型string

    <input
      class="form-control"
      :class="{ 'is-invalid': inputRef.error }"
      :value="modelValue"
      @blur="validateInput"
      @input="updateValue"
      v-bind="$attrs"
    />

設(shè)置了自定義事件用于更新value

//手動(dòng)更新value
const updateValue = (e: Event) => {
  //HTMLInputElement輸入元素類型
  let targetValue = (e.target as HTMLInputElement).value
  //更新文本框的值
  inputRef.val = targetValue
  emit('update:modelValue', targetValue)
}

因此實(shí)現(xiàn)v-model屬性

3. rules屬性

接收參數(shù)

  • type:校驗(yàn)類型,requied | email | range
  • message
  • min:至少幾位
  • max:至多幾位

抽象驗(yàn)證邏輯

validate-input組件

//數(shù)組類型
export type RulesProp = RuleProp[]
//接收參數(shù)
const props = defineProps<{
  rules?: RulesProp
  //自定義組件使用v-model需要用modelValue來接收參數(shù)
  modelValue: string
}>()

參數(shù)接收rules是個(gè)數(shù)組

//定義表單的數(shù)據(jù)
const inputRef = reactive({
  //如果為空
  val: props.modelValue || '',
  error: false, //表單驗(yàn)證是否通過
  message: '' //錯(cuò)誤信息
})

定義表單的數(shù)據(jù)

//定義事件
const validateInput = () => {
  //定義郵箱的正則
  let emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/
  //如果傳過來的有驗(yàn)證的話
  if (props.rules) {
    //every方法  遍歷全部數(shù)組只有全部滿足條件才會(huì)返回true, 只要有一個(gè)false停止遍歷
    let allRulePassed = props.rules.every(rule => {
      let passed = true
      //消息賦值 類型斷言
      inputRef.message = rule.message as string
      //switch選擇對(duì)應(yīng)type類型錯(cuò)誤進(jìn)行校驗(yàn)
      switch (rule.type) {
        case 'required':
          if (inputRef.val.trim() === '') {
            passed = false
          }
          break
        case 'email':
          if (!emailReg.test(inputRef.val)) {
            passed = false
          }
          break
        case 'range':
          passed = validateRange(rule.min, rule.max)
          break
      }
      return passed
    })
    //allRulePassed為false表示通過
    //所以Input.error表示錯(cuò)誤應(yīng)該為true
    inputRef.error = !allRulePassed
    return allRulePassed
  }
  return true
}

定義校驗(yàn)事件

滿足全部rules校驗(yàn)才可以通過,因此用到es6數(shù)組方法,every只有全部項(xiàng)都為true才會(huì)遍歷全部返回true,只要有一個(gè)項(xiàng)結(jié)果為false,就會(huì)停止遍歷

message校驗(yàn)信息賦值給inputRef.message

利用swicth case語句,選擇對(duì)應(yīng)的type類型進(jìn)行校驗(yàn)

需要充分考慮到所有情況,通過passed為true,未通過為fasle

range長度校驗(yàn),由于情況較多,單獨(dú)封裝一個(gè)函數(shù)去校驗(yàn)

//校驗(yàn)長度
const validateRange = (min: RangeProp | undefined, max: RangeProp | undefined) => {
  let passed = true
  //1. 如果min 存在 ,max不存在
  if (min && !max) {
    inputRef.message = min.message
    passed = !(inputRef.val.length < min.length)
  }
  //2. min不在, max在
  if (!min && max) {
    inputRef.message = max.message
    passed = !(inputRef.val.length > max.length)
  }
  //3. min在 max在
  if (min && max) {
    //若小于
    if (inputRef.val.length < min.length) {
      passed = false
      inputRef.message = min.message
    }
    //若大于
    if (inputRef.val.length > max.length) {
      passed = false
      inputRef.message = max.message
    }
  }
  return passed
}

模板中,根據(jù)passed的值,動(dòng)態(tài)綁定未通過的樣式

4. 默認(rèn)屬性

validate-input組件

  <div class="validate-input-container pb-3">
    <input
      class="form-control"
      :class="{ 'is-invalid': inputRef.error }"
      :value="modelValue"
      @blur="validateInput"
      @input="updateValue"
      v-bind="$attrs"
    />
    <span v-if="inputRef.error" class="invalid-feedback">{{ inputRef.message }}</span>
  </div>

父組件

          <Validate-input
            v-model="loginParams.password"
            :rules="passwordRules"
            type="password"
            placeholder="請(qǐng)輸入密碼"
          ></Validate-input>

通過顯示綁定attrs,使得自定義組件可以使用默認(rèn)屬性

ValidateInput 組件中,可以通過 $attrs 屬性將 type 屬性將被傳遞到組件的根元素上

可以在父組件中靈活地傳遞任何HTML屬性給 ValidateInput 組件,使它更加通用和可配置

四:封裝Validate-Form組件

事件

form-submit:點(diǎn)擊提交觸發(fā)的事件,回調(diào)參數(shù)result是布爾值,表示該表單是否通過了校驗(yàn)

1. form-submit事件

當(dāng)點(diǎn)擊提交時(shí),要去驗(yàn)證該表單是否通過了校驗(yàn),就需要一個(gè)個(gè)將表單項(xiàng)進(jìn)行校驗(yàn),只要一個(gè)沒通過就返回false,只有全部通過返回true

收集全部表單項(xiàng)校驗(yàn)函數(shù)

可以通過將所有表單項(xiàng)的校驗(yàn)函數(shù)都添加到一個(gè)數(shù)組中,然后最終通過every方法遍歷是否全部通過

收集

安裝mitt并使用,監(jiān)聽事件

npm install mitt --save

全局掛載

main.ts

import mitt from 'mitt'
//對(duì)外暴露全局事件總線實(shí)例
export const bus = mitt()

ValidateForm組件中使用

<script setup lang="ts">
import { onUnmounted, reactive } from 'vue'
import { bus } from '@/main'
const emits = defineEmits(['form-submit'])
//點(diǎn)擊事件
//定義函數(shù)類型
type ValidateFunc = () => boolean
//定義類型
//定義接收的函數(shù)數(shù)組
const funcArr = reactive<ValidateFunc[]>([])
//測(cè)試回調(diào)
const callback = (func: ValidateFunc) => {
  //將每個(gè)校驗(yàn)函數(shù)加入數(shù)組
  funcArr.push(func)
}
//訂閱事件
bus.on('form-item-created', callback as ValidateFunc)
//提交按鈕觸發(fā)事件
const submitForm = () => {
  const result = funcArr.map(func => func()).every(result => result)
  // 觸發(fā)提交事件
  //遍歷funcArr中的每個(gè)校驗(yàn)函數(shù)
  emits('form-submit', result)
}
onUnmounted(() => {
  // 移除訂閱
  bus.off('form-item-created', callback as ValidateFunc)
})
</script>
  • 定義函數(shù)類型,返回值為空
  • 利用泛型定義存放每個(gè)表單項(xiàng)校驗(yàn)函數(shù)存放的數(shù)組
  • 訂閱事件,在組件卸載的時(shí)候再取消訂閱

ValidateInput 組件中

組件掛載的時(shí)候,就直接觸發(fā)自定義事件,然后將每一項(xiàng)的校驗(yàn)函數(shù)傳遞給 ValidateForm組件

Validate-Form組件

然后接受ValidateInput組件傳遞過來的校驗(yàn)函數(shù),一個(gè)個(gè)加入到數(shù)組中

在submitForm事件中,遍歷數(shù)組,不能直接使用every方法,因?yàn)橹灰粋€(gè)不通過就不進(jìn)行后面的校驗(yàn),這是不滿足我們的需求的

可以看到下面的錯(cuò)誤實(shí)例,密碼原本也是不通過校驗(yàn)的,但是every方法直接在第一個(gè)校驗(yàn)失敗結(jié)束遍歷了

image-20230909220625051

因此先利用map函數(shù),先使得每個(gè)校驗(yàn)函數(shù)都執(zhí)行,結(jié)束后返回一個(gè)新的數(shù)組存放校驗(yàn)函數(shù)的返回值,再通過every遍歷數(shù)組

最后觸發(fā)自定義事件,將結(jié)果傳遞給父組件中

父組件

<Validate-Form @form-submit="submitForm" ref="validateFormRef">
const submitForm = (result: boolean) => {
  console.log(result)
}

提交表單元素后清空表單值

具體邏輯跟校驗(yàn)差不多

Validate-Form組件

<script setup lang="ts">
import { onUnmounted, reactive } from 'vue'
import { bus } from '@/main'
const emits = defineEmits(['form-submit'])
//點(diǎn)擊事件
//定義函數(shù)類型
type ValidateFunc = () => boolean
//定義清空Input函數(shù)類型
type clearInputsFunc = () => void
//定義類型
//定義接收的函數(shù)數(shù)組
const funcArr = reactive<ValidateFunc[]>([])
//定義接收用于清空的函數(shù)數(shù)組
const clearFuncArr = reactive<clearInputsFunc[]>([])
//測(cè)試回調(diào)
const callback = (func: ValidateFunc) => {
  //將每個(gè)校驗(yàn)函數(shù)加入數(shù)組
  funcArr.push(func)
}
//事件回調(diào)
const clearInputFunc = (func: clearInputsFunc) => {
  clearFuncArr.push(func)
}
//綁定監(jiān)聽事件
bus.on('form-item-created', callback as ValidateFunc)
bus.on('form-item-clear', clearInputFunc as clearInputsFunc)
//提交按鈕觸發(fā)事件
const submitForm = () => {
  const result = funcArr.map(func => func()).every(result => result)
  // 觸發(fā)提交事件
  //遍歷funcArr中的每個(gè)校驗(yàn)函數(shù)
  emits('form-submit', result)
  //遍歷清空函數(shù)數(shù)組并依次并執(zhí)行
  //當(dāng)校驗(yàn)通過時(shí)候才會(huì)清空input
  if (result) {
    clearFuncArr.map(func => func())
  }
}
onUnmounted(() => {
  // 移除事件監(jiān)聽器
  bus.off('form-item-created', callback as ValidateFunc)
  bus.off('form-item-clear', clearInputFunc as clearInputsFunc)
})
</script>

Validate-input組件

onMounted(() => {
  //直接把validateInput校驗(yàn)事件傳遞過去
  bus.emit('form-item-created', validateInput)
  //直接觸發(fā)事件先傳入每個(gè)input的值
  bus.emit('form-item-clear', clearInput)
})
//定義表單的數(shù)據(jù)
const inputRef = reactive({
  //如果為空
  val: props.modelValue || '',
  error: false, //表單驗(yàn)證是否通過
  message: '' //錯(cuò)誤信息
})

把清空表單數(shù)據(jù)的處理函數(shù)收集起來

最后利用map方法依次執(zhí)行清除即可

五:演示和使用

在 vue template 中添加結(jié)構(gòu)代碼

      <Validate-Form @form-submit="submitForm" ref="validateFormRef">
        <!-- 郵箱地址 -->
        <div class="mb-3">
          <label for="exampleInputEmail1" class="form-label">郵箱地址</label>
          <!-- 自定義組件Validate-input -->
          <Validate-input v-model="loginParams.email" :rules="emailRules" placeholder="請(qǐng)輸入郵箱地址"></Validate-input>
        </div>
        <!-- 密碼 -->
        <div class="mb-3">
          <label for="exampleInputPassword1" class="form-label">密碼</label>
          <Validate-input
            v-model="loginParams.password"
            :rules="passwordRules"
            type="password"
            placeholder="請(qǐng)輸入密碼"
          ></Validate-input>
        </div>
        <template #submit>
          <button type="submit" class="btn btn-primary btn-block btn-large">提交</button>
        </template>
      </Validate-Form>

在 setup語法糖中添加數(shù)據(jù)

//定義驗(yàn)證類型數(shù)據(jù)
const emailRules: RulesProp = [
  { type: 'required', message: '電子郵箱地址不能為空' },
  { type: 'email', message: '請(qǐng)輸入正確的電子郵箱格式' }
]
//定義密碼驗(yàn)證類型數(shù)據(jù)
const passwordRules: RulesProp = [
  { type: 'required', message: '密碼不能為空' },
  {
    type: 'range',
    min: { message: '你的密碼至少包括6位,不能含有空格', length: 6 },
    max: {
      message: '你的密碼至多15位,不能含有空格',
      length: 15
    }
  }
]
//監(jiān)聽結(jié)果
const submitForm = (result: boolean) => {
  console.log(result)
}

Validate-Form屬性和事件

form-submit:

類型:事件

默認(rèn):-

說明:回調(diào)參數(shù) (result: boolean) => void, result 代表是否通過了驗(yàn)證

Validate-Input屬性和事件

rules

  • 類型:array
  • 默認(rèn):-
  • 說明: 單個(gè)輸入框的驗(yàn)證類型,可以傳入包含特定對(duì)象的數(shù)組, 詳情可見上面示例代碼

tag

  • 類型:input | textarea
  • 默認(rèn):input
  • 說明: 根節(jié)點(diǎn)類型

v-model

  • 類型: string
  • 默認(rèn):-
  • 說明: 支持 v-model,請(qǐng)對(duì)響應(yīng)式數(shù)據(jù)

到此這篇關(guān)于Vue Validate表單組件的封裝詳解的文章就介紹到這了,更多相關(guān)Vue Validate內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue純前端使用exceljs導(dǎo)出excel文件方式

    vue純前端使用exceljs導(dǎo)出excel文件方式

    本文介紹了如何使用excel.js插件和Vue實(shí)現(xiàn)純前端Excel文件導(dǎo)出,并詳細(xì)步驟包括安裝插件、創(chuàng)建工作簿和工作表、定義列數(shù)據(jù)、設(shè)置樣式、行級(jí)操作、遍歷行和單元格、插入圖片和超鏈接
    2024-11-11
  • vue路由相對(duì)路徑跳轉(zhuǎn)方式

    vue路由相對(duì)路徑跳轉(zhuǎn)方式

    這篇文章主要介紹了vue路由相對(duì)路徑跳轉(zhuǎn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • element-ui復(fù)雜table表格動(dòng)態(tài)新增列、動(dòng)態(tài)調(diào)整行以及列順序詳解

    element-ui復(fù)雜table表格動(dòng)態(tài)新增列、動(dòng)態(tài)調(diào)整行以及列順序詳解

    這篇文章主要給大家介紹了關(guān)于element-ui復(fù)雜table表格動(dòng)態(tài)新增列、動(dòng)態(tài)調(diào)整行以及列順序的相關(guān)資料,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • vuejs父子組件之間數(shù)據(jù)交互詳解

    vuejs父子組件之間數(shù)據(jù)交互詳解

    這篇文章主要為大家詳細(xì)介紹了vuejs父子組件之間的數(shù)據(jù)交互,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Vue vm.$attrs使用場(chǎng)景詳解

    Vue vm.$attrs使用場(chǎng)景詳解

    這篇文章主要介紹了vm.$attrs使用場(chǎng)景詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • vue子組件實(shí)時(shí)獲取父組件的數(shù)據(jù)實(shí)現(xiàn)

    vue子組件實(shí)時(shí)獲取父組件的數(shù)據(jù)實(shí)現(xiàn)

    本文主要介紹了vue子組件實(shí)時(shí)獲取父組件的數(shù)據(jù)實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • Vue.js動(dòng)態(tài)添加、刪除選題的實(shí)例代碼

    Vue.js動(dòng)態(tài)添加、刪除選題的實(shí)例代碼

    這篇文章主要介紹了Vue.js動(dòng)態(tài)添加、刪除選題的實(shí)例代碼,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • vue3實(shí)現(xiàn)淘寶放大鏡效果的示例代碼

    vue3實(shí)現(xiàn)淘寶放大鏡效果的示例代碼

    放大鏡效果在很多購物網(wǎng)站都可以看到,本文主要介紹了vue3實(shí)現(xiàn)淘寶放大鏡效果的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • vue中改變了vuex數(shù)據(jù)視圖不更新,也監(jiān)聽不到的原因及解決

    vue中改變了vuex數(shù)據(jù)視圖不更新,也監(jiān)聽不到的原因及解決

    這篇文章主要介紹了vue中改變了vuex數(shù)據(jù)視圖不更新,也監(jiān)聽不到的原因及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • vue中v-if失效原因及解決方法

    vue中v-if失效原因及解決方法

    本文主要介紹了vue中v-if失效原因及解決方法,一般v-if失效都是和綁定變量有關(guān),下面就來具體介紹一下,感興趣的可以了解一下
    2023-09-09

最新評(píng)論