您好,登錄后才能下訂單哦!
表單是后臺項目業務中的常用組件,這次重構了登錄功能以滿足登錄方式可配置的需求,在此記錄和分享一下。
業務場景
在之前,項目只支持手機號+密碼登錄,前端是直接把表單寫死的,后來有客戶希望能支持驗證碼登錄,有的客戶還希望能有手機號+驗證碼+密碼的登錄方式…所以登錄方式的靈活性需要可配置的表單支持,于是我把登錄組件做了拆分。
以表單元素為粒度,分離出了手機號、密碼、短信驗證碼這幾個組件,它們內部都有自己的表單驗證方法,通過組合可以快速完成登錄、注冊、找回密碼等表單組件。高內聚低耦合、高內聚低耦合…跟著念十遍~
. ├ common ├ captcha.vue | ├ password.vue | └ phone.vue ├ login | └ index.vue ├ register | └ index.vue └ resetPassword └ index.vue
這里我們將login作為父組件,讀取服務端返回的登錄配置并在模板做條件渲染,登錄時調用子組件內部的表單驗證,最后通過Vuex拿到數據調用接口。整個可配置登錄表單的邏輯就是醬子,接下來上代碼。
代碼
請求服務端配置數據:
/* 參數說明: * 'password': 密碼登錄 * 'captcha': 短信驗證碼登錄 * 'password_or_captcha': 密碼或短信登錄 * 'password_with_captcha': 密碼+短信登錄 */ config: { login_methods: 'password' }
登錄組件的核心渲染代碼(pug):
.login-card .login-header h4 登錄 .login-content phone(ref="phone") password( v-if="isPasswordMode" ref="password" ) captcha( v-if="isCaptchaMode" ref="captcha" ) template(v-if="isPasswordWithCaptchaMode") captcha(ref="captcha") password(ref="password") template(v-if="isPasswordOrCaptchaMode") ... el-button(@click="login") 登錄
登錄時需要三個步驟:表單驗證、組裝數據、調用接口:
async login () { if (!this.validate()) return const loginData = this.getLoginData() await this.postLogin(loginData) ... }
登錄的表單驗證其實是對當前登錄方式中所有組件的 validate() 方法進行邏輯判斷:
validate () { const phone = this.$refs.phone.validate() let isPass = false if (this.isPasswordMode) { if (this.$refs.password) isPass = this.$refs.password.validate() } if (this.isCaptchaMode) { if (this.$refs.captcha) isPass = this.$refs.captcha.validate() } if (this.isPasswordWithCaptchaMode) ... if (this.isPasswordOrCaptchaMode) ... isPass = phone && isPass return isPass }
每個子組件都是一個完整的表單,驗證也由自己完成,password組件模板:
.login-password el-form( :model="form" :rules="rules" ref="form" @submit.native.prevent="" ) el-form-item(prop="password") el-input( v-model="form.password" type="password" name="password" )
W3C: When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.
需要注意,根據 W3C標準 , 當一個form元素中只有一個輸入框時,在該輸入框中按下回車會自動提交表單。通過在 <el-form> 添加 @submit.native.prevent 可以阻止這一默認行為。
password組件的表單驗證:
validate () { let res = false this.$refs.form.validate((valid) => { res = valid }) return res }
最后從Vuex里拿到所有表單數據,進行組裝:
computed: { ...mapState('login', { phone: state => state.phone, password: state => state.password, captcha: state => state.captcha }), }, methods: { ... getLoginData () { let mode = '' const phone = this.phone ... const data = { phone } if (this.isPasswordMode) { mode = 'password' data.password = password } if (this.isCaptchaMode) { mode = 'captcha' data.captcha = captcha } if (this.isPasswordWithCaptchaMode) ... if (this.isPasswordOrCaptchaMode) ... data.mode = mode return data } }
補充:
vue.js 全選與取消全選的實例代碼
new Vue({ el: '#app', data: { checked: false, checkedNames: [], checkedArr: ["Runoob", "Taobao", "Google"] }, methods: { changeAllChecked: function() { if (this.checked) { this.checkedNames = this.checkedArr } else { this.checkedNames = [] } } }, watch: { "checkedNames": function() { if (this.checkedNames.length == this.checkedArr.length) { this.checked = true } else { this.checked = false } } } })
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。