vue3如何優(yōu)雅的實(shí)現(xiàn)移動(dòng)端登錄注冊(cè)模塊
前言
近期開(kāi)發(fā)的移動(dòng)端項(xiàng)目直接上了 vue3 ,新特性 composition api 確實(shí)帶來(lái)了全新的開(kāi)發(fā)體驗(yàn).開(kāi)發(fā)者在使用這些特性時(shí)可以將高耦合的狀態(tài)和方法放在一起統(tǒng)一管理,并能視具體情況將高度復(fù)用的邏輯代碼單獨(dú)封裝起來(lái),這對(duì)提升整體代碼架構(gòu)的健壯性很有幫助.
如今新啟動(dòng)的每個(gè)移動(dòng)端項(xiàng)目基本上都包含注冊(cè)登錄模塊,本次實(shí)踐過(guò)程中針對(duì)登錄注冊(cè)中的表單控件做了一些經(jīng)驗(yàn)上的總結(jié),通過(guò)抽離提取共性代碼來(lái)提升代碼的可維護(hù)性和開(kāi)發(fā)效率.
接下來(lái)觀察一下美工同學(xué)提供的圖片.
注冊(cè)頁(yè)面

登錄頁(yè)面

忘記密碼頁(yè)面

修改密碼頁(yè)面

通過(guò)觀察上面幾張產(chǎn)品圖片,可以清晰看出構(gòu)成整個(gè)登錄注冊(cè)模塊的核心組件就是 input 輸入框.只要把輸入框組件開(kāi)發(fā)完備,其他頁(yè)面直接引用就行了.
輸入框開(kāi)發(fā)完了只實(shí)現(xiàn)了靜態(tài)頁(yè)面的展示,另外我們還要設(shè)計(jì)一套通用的數(shù)據(jù)校驗(yàn)方案應(yīng)用到各個(gè)頁(yè)面中的表單控件.
輸入框組件
從上面分析可知,輸入框組件是整個(gè)登錄注冊(cè)模塊的核心內(nèi)容.我們先看一下輸入框組件有哪幾種 UI 形態(tài).
形態(tài)一

左側(cè)有文字 +86 ,中間是輸入框,右側(cè)如果檢測(cè)到輸入框有數(shù)據(jù)輸入顯示叉叉圖標(biāo),如果沒(méi)有數(shù)據(jù)為空隱藏圖標(biāo).
形態(tài)二

左側(cè)只有一個(gè)輸入框,右側(cè)是文案.文案的內(nèi)容可能是驗(yàn)證碼,也可能是點(diǎn)擊驗(yàn)證碼后顯示的倒計(jì)時(shí)文案.
形態(tài)三

左側(cè)依舊只有一個(gè)輸入框,右側(cè)如果檢測(cè)到輸入框有內(nèi)容顯示叉叉圖標(biāo),如果內(nèi)容為空隱藏圖標(biāo).
布局
依據(jù)上面觀察而來(lái)的現(xiàn)象分析,我們?cè)O(shè)計(jì)這款 input 組件時(shí)可以將其分為左中右三部分.左側(cè)可能是文案,也可能是空.中間是一個(gè)輸入框.右側(cè)可能是文案也可能是叉叉圖標(biāo).
模板內(nèi)容如下:
<template>
<div class="input">
<!--左側(cè),lt是左側(cè)內(nèi)容-->
<span class="left-text">
{{ lt }}
</span>
<!--中間-->
<input class="content" v-bind="$attrs" :value="value" @input="onChange" />
<!--右側(cè),rt判端是驗(yàn)證碼還是叉叉圖標(biāo)-->
<div v-if="rt == 'timer'" class="right-section">
{{ timerData.content }} <!--可能是'驗(yàn)證碼',也可能是倒計(jì)時(shí) -->
</div>
<div
v-else-if="rt == 'close'"
class="right-section"
>
<van-icon name="close" /> <!--叉叉圖標(biāo)-->
</div>
</div>
</template>
布局上將左中右的父級(jí)設(shè)置為 display:flex ,子級(jí)的三個(gè)元素全部設(shè)置成 display:inline-block 行內(nèi)塊模式,目的是為了讓左側(cè)和右側(cè)依據(jù)自身內(nèi)容自適應(yīng)寬度,而中間的 input 設(shè)置成 flex:1 充滿剩余的寬度.
理論上這樣的布局是可行的,但實(shí)踐中發(fā)現(xiàn)了問(wèn)題.
Demo 效果圖如下:

右側(cè)持續(xù)增加寬度時(shí),中間 input 由于默認(rèn)寬度的影響導(dǎo)致讓右側(cè)向外溢出了,這并不是我們想要的.
解決這個(gè)問(wèn)題的辦法很簡(jiǎn)單,只需要將中間 input 的 width 設(shè)置為 0 即可,如下便達(dá)到了我們想要的效果.

v-model
外部頁(yè)面引用上述封裝的組件結(jié)構(gòu)如下:
<InputForm lt="+86" <!--左側(cè)顯示+86--> rt="close" <!--右側(cè)顯示叉叉圖標(biāo)--> placeholder="請(qǐng)輸入手機(jī)號(hào)碼" />
外部頁(yè)面創(chuàng)建了一個(gè)表單數(shù)據(jù) form_data 如下,但希望能通過(guò) v-model 的形式將 form_data 的數(shù)據(jù)與子組件輸入框的值建立雙向數(shù)據(jù)綁定.
const form_data = reactive({
number_number: '', //用戶名
password: '', //密碼
ppassword: '', //重復(fù)密碼
captcha: '', //驗(yàn)證碼
})
在 vue3 實(shí)現(xiàn) v-model 非常簡(jiǎn)便,在父組件中使用 v-model:xx 完成綁定,這里的 xx 對(duì)應(yīng)著子組件要綁定的狀態(tài)名稱(chēng),如下所示.
<InputForm
lt="+86" <!--左側(cè)顯示+86-->
rt="close" <!--右側(cè)顯示叉叉圖標(biāo)-->
placeholder="請(qǐng)輸入手機(jī)號(hào)碼"
v-model:value="form_data.password"
/>
接下來(lái)子組件里首先聲明要綁定的屬性 value ,并監(jiān)聽(tīng)輸入框的 oninput事件 .代碼如下:
<template>
<div class="input">
...
<input class="content" v-bind="$attrs" :value="value" @input="onChange" />
...
</div>
</template>
export default defineComponent({
props: {
lt:String,
rt: String,
value: String
},
setup(props, context) {
const onChange = (e:KeyboardEvent) => {
const value = (e.target as HTMLInputElement).value;
context.emit("update:value",value);
};
return {
onChange
}
}
})
oninput事件 的回調(diào)函數(shù)將獲取到的值使用 context.emit("update:value",value) 返回回去.
其中 update:value 里前面部分 update: 為固定寫(xiě)法,后面填寫(xiě)要建立雙向綁定的狀態(tài)名稱(chēng).如此一來(lái)就輕易的完成了 v-model 的綁定.
數(shù)據(jù)校驗(yàn)
一般來(lái)說(shuō)只要頁(yè)面上涉及到表單控件(比如輸入框),那么就要針對(duì)相應(yīng)的值做數(shù)據(jù)校驗(yàn).如果按照原始的方法,當(dāng)用戶點(diǎn)擊按鈕, js 接受響應(yīng)依次獲取每個(gè)表單項(xiàng)的值一一校驗(yàn).
這樣的做法當(dāng)然可以實(shí)現(xiàn)功能,但并不高效和精簡(jiǎn).因?yàn)楹芏囗?yè)面都要做校驗(yàn),大量的校驗(yàn)邏輯是重復(fù)書(shū)寫(xiě)的.
我們接下來(lái)設(shè)計(jì)一套通用的校驗(yàn)方案,將那些可以復(fù)用的邏輯代碼都封裝起來(lái),并且能夠快速的應(yīng)用到每個(gè)頁(yè)面上,提升開(kāi)發(fā)效率.
依注冊(cè)頁(yè)面為例,模板代碼如下.創(chuàng)建四個(gè)輸入框組件:手機(jī)號(hào),手機(jī)驗(yàn)證碼,密碼和確認(rèn)密碼.最后面再放置一個(gè)注冊(cè)按鈕.(為了看起來(lái)更清晰,下面的代碼將所有 ts 類(lèi)型刪除)
<Form ref="form" :rules="rules">
<InputForm
lt="+86"
rt="close"
v-model:value="form_data.number_number"
placeholder="請(qǐng)輸入手機(jī)號(hào)碼"
propName="number_number"
/>
<InputForm
rt="timer"
v-model:value="form_data.captcha"
placeholder="請(qǐng)輸入手機(jī)驗(yàn)證碼"
propName="captcha"
/>
<InputForm
rt="close"
v-model:value="form_data.password"
placeholder="請(qǐng)輸入密碼"
type="password"
propName="password"
/>
<InputForm
rt="close"
v-model:value="form_data.ppassword"
placeholder="請(qǐng)輸入確認(rèn)密碼"
type="password"
propName="ppassword"
/>
<Button text="注 冊(cè)" @sub="onSubmmit" /> <!--注冊(cè)按鈕-->
</Form>
在借鑒了一些其他優(yōu)秀框架的表單實(shí)踐后,我們首先是在最外層增加了一個(gè)組件 Form ,其次給每個(gè)輸入框組件增加了一個(gè)屬性 propName .這個(gè)屬性是配合 rules 一起使用的, rules 是手動(dòng)定義的校驗(yàn)規(guī)則,當(dāng)它傳遞給 Form 組件后,子組件(輸入框組件)就能通過(guò) propName 屬性拿到屬于它的校驗(yàn)規(guī)則.
整體的實(shí)現(xiàn)思路可以從頭串聯(lián)一遍.首先是前端開(kāi)發(fā)者定義好當(dāng)前頁(yè)面的校驗(yàn)規(guī)則 rules ,并將它傳遞給 Form 組件. Form 組件接受到后會(huì)將校驗(yàn)規(guī)則分發(fā)給它的每個(gè)子組件(輸入框組件).子組件拿到校驗(yàn)規(guī)則后就能夠針對(duì)輸入框的值做相應(yīng)的數(shù)據(jù)校驗(yàn).
當(dāng)用戶點(diǎn)擊注冊(cè)按鈕時(shí),點(diǎn)擊事件會(huì)獲取 Form 組件的實(shí)例,并運(yùn)行它的 validate 方法,此時(shí) Form 組件就會(huì)對(duì)它旗下的每個(gè)子組件做一輪數(shù)據(jù)校驗(yàn).一旦所有校驗(yàn)成功了, validate 方法返回 true .存在一個(gè)校驗(yàn)沒(méi)通過(guò), validate 方法就返回 false ,并彈出錯(cuò)誤信息.
注冊(cè)頁(yè)面邏輯如下:
export default defineComponent({
components: {
InputForm, //輸入框
Button, //注冊(cè)按鈕
Form, //Form組件
},
setup(props) {
const form_data = ...; //省略
const rules = ...;
//獲取最外層Form組件的實(shí)例
const form = ref(null);
const onSubmmit = ()=>{
if (!form.value || !form.value.validate()) {
return false;
}
//校驗(yàn)通過(guò)了,可以請(qǐng)求注冊(cè)接口了
}
return {
form,
rules,
onSubmmit,
form_data
};
},
});
定義一個(gè)變量 form ,用它來(lái)獲取 Form 表單的實(shí)例.模板上 <Form ref="form" :rules="rules"> 只需要加上一個(gè) ref 屬性就可以了.
用戶點(diǎn)擊注冊(cè)按鈕觸發(fā) onSubmmit 函數(shù),因?yàn)?form 是使用 ref 創(chuàng)建的變量,獲取值要調(diào)用 .value .運(yùn)行 form.value.validate() 函數(shù),就能讓 Form 表單下面的每一個(gè)子組件開(kāi)始執(zhí)行校驗(yàn)邏輯,如果全部通過(guò)就會(huì)返回 true ,存在一個(gè)沒(méi)通過(guò)返回 false .
從上面分析可知, Form 控件只對(duì)外暴露一個(gè) validate 函數(shù),通過(guò)調(diào)用該函數(shù)就能知道校驗(yàn)是否通過(guò).那么 validate 如何知道該采用什么規(guī)則來(lái)校驗(yàn)?zāi)?#63;所以我們要先設(shè)計(jì)一套校驗(yàn)的規(guī)則 rules ,把它傳給 Form 組件,那么它內(nèi)部的 validate 函數(shù)就能采用規(guī)則來(lái)執(zhí)行校驗(yàn).
rules設(shè)計(jì)
rules 是一個(gè)對(duì)象,例如上述注冊(cè)頁(yè)面的 rules 定義如下:
const rules = {
number_number:[{
type: 'required',
msg:"請(qǐng)輸入正確的手機(jī)號(hào)"
}
"phone"
],
captcha:[
{
type: 'required',
msg: '驗(yàn)證碼不能為空'
}
],
password: [
{
type: 'required',
msg: '請(qǐng)輸入密碼',
},
{
type: 'minLength',
params: 6,
msg: '密碼長(zhǎng)度不能小于6位',
},
],
ppassword:[
{
type: 'custome',
callback() {
if (form_data.password !== form_data.ppassword) {
return {
flag: false,
msg: '兩次輸入的密碼不一致',
};
}
return {
flag: true,
};
},
},
]
}
我們定義的 rules 是一個(gè)鍵值對(duì)形式的對(duì)象. key 對(duì)應(yīng)著模板上每個(gè)輸入框組件的 propName ,值是一個(gè)數(shù)組,對(duì)應(yīng)著該輸入框組件要遵守的規(guī)則.
現(xiàn)在細(xì)致的看下每個(gè)對(duì)象下的值的構(gòu)成,值之所以組織成數(shù)組形式,是因?yàn)檫@樣可以給輸入框增加多條規(guī)則.而規(guī)則對(duì)應(yīng)著兩種形式,一種是對(duì)象,另外一種是字符串.
字符串很好理解,比如上面的 number_number 屬性,它就對(duì)應(yīng)著字符串 phone .這條規(guī)則的意義就是該輸入框的值要遵守手機(jī)號(hào)的規(guī)則.當(dāng)然字符串如果填 email ,那就要當(dāng)做郵箱來(lái)校驗(yàn).
規(guī)則如果為對(duì)象,那么它包含了以下幾個(gè)屬性:
{
type, // 類(lèi)型
msg, //自定義的錯(cuò)誤信息
params, //傳過(guò)來(lái)的參數(shù)值 比如 {type:'minLength',params:6},值最小長(zhǎng)度不能低于6位
callback //自定義校驗(yàn)函數(shù)
}
type 是校驗(yàn)類(lèi)型,它如果填 required ,表示是必填項(xiàng).如果用戶沒(méi)填,點(diǎn)擊注冊(cè)按鈕提交時(shí)就會(huì)報(bào)出 msg 定義的錯(cuò)誤信息.
另外 type 還可以填 minLength 或者 maxLength 用來(lái)限定值的長(zhǎng)度,那到底限定為幾位呢,可以通過(guò) params 傳遞過(guò)去.
最后 type 還可以填 custome ,那么就是讓開(kāi)發(fā)者自己來(lái)定義該輸入框的校驗(yàn)邏輯函數(shù) callback .該函數(shù)要求最后返回一個(gè)帶有 flag 屬性的對(duì)象,屬性 flag 為布爾值,它會(huì)告訴校驗(yàn)系統(tǒng)本次校驗(yàn)是成功還是失敗.
Form表單
rules 被定義好后傳給 Form 組件, Form 組件需要將校驗(yàn)邏輯分發(fā)給它的子組件.讓其每個(gè)子組件都負(fù)責(zé)生成自己的校驗(yàn)函數(shù).
<!-- 表單組件 -->
<template>
<div class="form">
<slot></slot>
</div>
</template>
<script lang="ts">
import { ref, provide } from "vue";
export default defineComponent({
name: "Form",
props:{
rules:Object
},
setup(props) {
...//省略
provide("rules",props.rules); // 將校驗(yàn)規(guī)則分發(fā)下去
const validate = ()=>{
//向外暴露的校驗(yàn)函數(shù)
}
return {
validate
}
}
})
</script>
從上面結(jié)構(gòu)可以看出, Form 組件模板提供了一個(gè)插槽的作用,在邏輯代碼里利用 provide 將校驗(yàn)規(guī)則傳給后代,并向外暴露一個(gè) validate 函數(shù).
子組件生成校驗(yàn)函數(shù)
這一次又回到了登錄注冊(cè)模塊的核心組件 InputForm ,我們現(xiàn)在要給該輸入框組件添加校驗(yàn)邏輯.
import { inject,onMounted } from "vue";
...
setup(props, context) {
const rules = inject("rules");
const rule = rules[props.propName];// 通過(guò)propName拿到校驗(yàn)規(guī)則
const useValidate = () => {
const validateFn = getValidate(rule); // 獲取校驗(yàn)函數(shù)
const execValidate = () => {
return validateFn(props.value); //執(zhí)行校驗(yàn)函數(shù)并返回校驗(yàn)結(jié)果
};
onMounted(() => {
const Listener = inject('collectValidate');
if (Listener) {
Listener(execValidate);
}
});
};
useValidate(); //初始化校驗(yàn)邏輯
...
}
rules 結(jié)構(gòu)類(lèi)似如下.通過(guò) inject 和 propName 可以拿到 Form 分發(fā)給該輸入框要執(zhí)行的規(guī)則 rule .
{
captcha:[{
type: 'required',
msg: '驗(yàn)證碼不能為空'
}],
password:[{
type: 'required',
msg: '請(qǐng)輸入密碼',
}]
}
再將規(guī)則 rule 傳遞給 getValidate 函數(shù)(后面會(huì)講)獲取校驗(yàn)函數(shù) validateFn .校驗(yàn)函數(shù) validateFn 傳入輸入框的值就能返回校驗(yàn)結(jié)果.在這里把 validateFn 封裝了一層賦予 execValidate 給外部使用.
在上面的代碼中我們還看到了 onMounted 包裹的邏輯代碼.當(dāng)組件掛載完畢后,使用 inject 拿到 Form 組件傳遞下來(lái)的一個(gè)函數(shù) Listener ,并將校驗(yàn)函數(shù) execValidate 作為參數(shù)傳遞進(jìn)去執(zhí)行.
我們?cè)倩氐较旅娲a中的 Form 組件,看一下 Listener 是一個(gè)什么樣的函數(shù).
setup(props) {
const list = ref([]);//定義一個(gè)數(shù)組
const listener = (fn) => {
list.value.push(fn);
};
provide("collectValidate", listener); //將監(jiān)聽(tīng)函數(shù)分發(fā)下去
//驗(yàn)證函數(shù)
const validate = (propName) => {
const array = list.value.map((fn) => {
return fn();
});
const one = array.find((item) => {
return item.flag === false;
});
if (one && one.msg) {
//驗(yàn)證不通過(guò)
Alert(one.msg);//彈出錯(cuò)誤提示
return false;
} else {
return true;
}
};
...
從上面可以看出, Form 組件將 listener 函數(shù)分發(fā)了下去.而子組件在 onMounted 的生命周期鉤子里,獲取到分發(fā)下來(lái)的 listener 函數(shù),并將子組件內(nèi)部定義的校驗(yàn)函數(shù) execValidate 作為參數(shù)傳遞進(jìn)去執(zhí)行.
這樣一來(lái)就可以確保每個(gè)子組件一旦掛載完畢就會(huì)把自己的校驗(yàn)函數(shù)傳遞給 Form 組件中的 list 收集.而 Form 組件的 validate 方法只需要循環(huán)遍歷 list ,就可以依次執(zhí)行每個(gè)子組件的校驗(yàn)函數(shù).如果都校驗(yàn)通過(guò)了,給外部頁(yè)面返回 true .存在一個(gè)不通過(guò),彈出錯(cuò)誤提示返回 false .
走到這里整個(gè)校驗(yàn)的流程已經(jīng)打通了. Form 首先向子組件分發(fā)校驗(yàn)規(guī)則,子組件獲取規(guī)則生成自己的校驗(yàn)函數(shù),并且在其掛載完畢后將校驗(yàn)函數(shù)再返回給 Form 收集起來(lái).這個(gè)時(shí)候 Form 組件向外暴露的 validate 函數(shù)就可以實(shí)現(xiàn)針對(duì)所有表單控件的數(shù)據(jù)校驗(yàn).
接下來(lái)最后一步研究子組件如果通過(guò)規(guī)則來(lái)生成自己的校驗(yàn)函數(shù).
校驗(yàn)
首先編寫(xiě)一個(gè)管理校驗(yàn)邏輯的類(lèi) Validate .代碼如下.我們可以不斷的根據(jù)新需求擴(kuò)充該類(lèi)的方法,比如另外再增加 email 或者 maxLength 方法.
class Validate {
constructor() {}
required(data) { //校驗(yàn)是否為必填
const msg = '該信息為必填項(xiàng)'; //默認(rèn)錯(cuò)誤信息
if (data == null || (typeof data === 'string' && data.trim() === '')) {
return {
flag:false,
msg
}
}
return {
flag:true
}
}
//校驗(yàn)是否為手機(jī)號(hào)
phone(data) {
const msg = '請(qǐng)?zhí)顚?xiě)正確的手機(jī)號(hào)碼'; //默認(rèn)錯(cuò)誤信息
const flag = /^1[3456789]\d{9}$/.test(data);
return {
msg,
flag
}
}
//校驗(yàn)數(shù)據(jù)的最小長(zhǎng)度
minLength(data, { params }) {
let minLength = params; //最小為幾位
if (data == null) {
return {
flag:false,
msg:"數(shù)據(jù)不能為空"
}
}
if (data.trim().length >= minLength) {
return {flag:true};
} else {
return {
flag:false,
msg:`數(shù)據(jù)最小長(zhǎng)度不能小于${minLength}位`
}
}
}
}
Validate 類(lèi)定義的所有方法中,第一個(gè)參數(shù) data 是被校驗(yàn)的值,第二個(gè)參數(shù)是在頁(yè)面定義每條 rule 中的規(guī)則.形如 {type: 'minLength', params: 6, msg: '密碼長(zhǎng)度不能小于6位'} .
Validate 類(lèi)中每個(gè)方法最終的返回的數(shù)據(jù)結(jié)構(gòu)形如 {flag:true,msg:""} .結(jié)果中 flag 就來(lái)標(biāo)識(shí)校驗(yàn)是否通過(guò), msg 為錯(cuò)誤信息.
校驗(yàn)類(lèi) Validate 提供了各種各樣的校驗(yàn)方法,接下來(lái)運(yùn)用一個(gè)單例模式生成該類(lèi)的一個(gè)實(shí)例,將實(shí)例對(duì)象應(yīng)用到真實(shí)的校驗(yàn)場(chǎng)景中.
const getInstance = (function(){
let _instance;
return function(){
if(_instance == null){
_instance = new Validate();
}
return _instance;
}
})()
通過(guò)調(diào)用 getInstance 函數(shù)就可以得到單例的 Validate 實(shí)例對(duì)象.
輸入框組件通過(guò)給 getValidate 函數(shù)傳入一條 rule ,就能返回該組件需要的校驗(yàn)函數(shù).接下來(lái)看一下 getValidate 函數(shù)是如何通過(guò) rule 來(lái)生成校驗(yàn)函數(shù)的,代碼如下:
/**
* 生成校驗(yàn)函數(shù)
*/
export const getValidate = (rule) => {
const ob = getInstance();//獲取 Validate類(lèi) 實(shí)例對(duì)象
const fn_list = []; //將所有的驗(yàn)證函數(shù)收集起來(lái)
//遍歷rule數(shù)組,根據(jù)其類(lèi)型獲取Validate類(lèi)中的校驗(yàn)方法放到fn_list中收集起來(lái)
rule.forEach((item) => {
if (typeof item === 'string') { // 字符串類(lèi)型
fn_list.push({
fn: ob[item],
});
} else if (isRuleType(item)) { // 對(duì)象類(lèi)型
fn_list.push({
//如果item.type為custome自定義類(lèi)型,校驗(yàn)函數(shù)直接使用callback.否則從ob實(shí)例獲取
...item,
fn: item.type === 'custome' ? item.callback : ob[item.type],
});
}
});
//需要返回的校驗(yàn)函數(shù)
const execuate = (value) => {
let flag = true,
msg = '';
for (let i = 0; i < fn_list.length; i++) {
const item = fn_list[i];
const result = item.fn.apply(ob, [value, item]);//item.fn對(duì)應(yīng)著Validate類(lèi)定義的的校驗(yàn)方法
if (!result.flag) {
//驗(yàn)證沒(méi)有通過(guò)
flag = false;
msg = item.msg ? item.msg : result.msg;//是使用默認(rèn)的報(bào)錯(cuò)信息還是用戶自定義信息
break;
}
}
return {
flag,
msg,
};
};
return execuate;
};
rule 的數(shù)據(jù)結(jié)構(gòu)形類(lèi)似如下代碼.當(dāng)把 rule 傳入 getValidate 函數(shù),它會(huì)判端是對(duì)象還是字符串,隨后將其類(lèi)型對(duì)應(yīng)的校驗(yàn)函數(shù)從 ob 實(shí)例中獲取存儲(chǔ)到 fn_list 中.
[
{
type: 'required',
msg: "請(qǐng)輸入電話號(hào)碼"
},
"phone"
]
getValidate 函數(shù)最終返回 execuate 函數(shù),此函數(shù)也正是輸入框組件得到的校驗(yàn)函數(shù).在輸入框組件里是可以拿到輸入框值的,如果將值傳給 execuate 方法調(diào)用.方法內(nèi)部就會(huì)遍歷之前緩存的校驗(yàn)函數(shù)列表 fn_list ,將值傳入每個(gè)校驗(yàn)方法運(yùn)行就能獲取該輸入框組件對(duì)當(dāng)前值的校驗(yàn)結(jié)果并返回回去.
以上校驗(yàn)的邏輯也已經(jīng)走通了.接下來(lái)不管是開(kāi)發(fā)登錄頁(yè),忘記密碼或者修改密碼的頁(yè)面,只需要使用 Form 組件和輸入框 InputForm 組件組織頁(yè)面結(jié)構(gòu),并寫(xiě)一份當(dāng)前頁(yè)面的 rules 校驗(yàn)規(guī)則即可.剩下的所有校驗(yàn)細(xì)節(jié)和交互動(dòng)作全部交給了 Form 和 InputForm 內(nèi)部處理,這樣會(huì)極大的提升開(kāi)發(fā)效率.
最終效果

總結(jié)
到此這篇關(guān)于vue3如何優(yōu)雅的實(shí)現(xiàn)移動(dòng)端登錄注冊(cè)模塊的文章就介紹到這了,更多相關(guān)vue3移動(dòng)端登錄注冊(cè)模塊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項(xiàng)目npm?run?build打包dist文件及打包后空白解決辦法
npm run build 這個(gè)命令會(huì)執(zhí)行Vue CLI中預(yù)定義的打包配置,并將打包后的文件存放在"dist"文件夾中,這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目npm?run?build打包dist文件及打包后空白的解決辦法,需要的朋友可以參考下2023-10-10
解決Vue項(xiàng)目中Emitted value instead of an 
這篇文章主要介紹了解決Vue項(xiàng)目中Emitted value instead of an instance of Error問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Vue項(xiàng)目中如何運(yùn)用vuex的實(shí)戰(zhàn)記錄
如果說(shuō)是JQuery是手工作坊,那么Vue.js就像是一座工廠,雖然Vue.js做的任何事情JQuery都可以做,但無(wú)論是代碼量還是流程規(guī)范性都是前者較優(yōu),下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中如何運(yùn)用vuex的相關(guān)資料,需要的朋友可以參考下2021-09-09
vue中生成條形碼(jsbarcode)和二維碼(qrcodejs2)的簡(jiǎn)單示例
在vue項(xiàng)目中難免遇到有要生成條形碼或者二維碼的功能需求,下面這篇文章主要給大家介紹了關(guān)于vue中生成條形碼(jsbarcode)和二維碼(qrcodejs2)的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
解決vue父組件調(diào)用子組件只執(zhí)行一次問(wèn)題
開(kāi)發(fā)中,需求是將內(nèi)容展示作為一個(gè)組件,輸入為contentId,請(qǐng)求在組件中,只需根據(jù)父組件傳過(guò)來(lái)的contentId去請(qǐng)求內(nèi)容的詳情即可,但是過(guò)程中卻發(fā)現(xiàn)一個(gè)問(wèn)題,父組件調(diào)用子組件只執(zhí)行一次,所以本文就給大家介紹解決vue父組件調(diào)用子組件只執(zhí)行一次問(wèn)題2023-09-09
vue在App.vue文件中監(jiān)聽(tīng)路由變化刷新頁(yè)面操作
這篇文章主要介紹了vue在App.vue文件中監(jiān)聽(tīng)路由變化刷新頁(yè)面操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Element中table組件按照屬性執(zhí)行合并操作詳解
在我們?nèi)粘i_(kāi)發(fā)中,表格業(yè)務(wù)基本是必不可少的,對(duì)于老手來(lái)說(shuō)確實(shí)簡(jiǎn)單,家常便飯罷了,但是對(duì)于新手小白如何最快上手搞定需求呢?本文從思路開(kāi)始著手,幫你快速搞定表格2022-11-11
Vue.js中provide/inject實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)更新的方法示例
這篇文章主要介紹了Vue.js中provide/inject實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)更新,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10

