国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網易首頁 > 網易號 > 正文 申請入駐

設計Element UI表單組件居然如此簡單!

0
分享至

點擊下方“JavaEdge”,選擇“設為星標”

第一時間關注技術干貨!


免責聲明~ 任何文章不要過度深思! 萬事萬物都經不起審視,因為世上沒有同樣的成長環(huán)境,也沒有同樣的認知水平,更「沒有適用于所有人的解決方案」; 不要急著評判文章列出的觀點,只需代入其中,適度審視一番自己即可,能「跳脫出來從外人的角度看看現(xiàn)在的自己處在什么樣的階段」才不為俗人。 怎么想、怎么做,全在乎自己「不斷實踐中尋找適合自己的大道」

0 前言

上文講解了Jest框架對組件庫測試,TypeScript和Jest都為代碼質量和研發(fā)效率。之前實現(xiàn)Container和Button組件以渲染功能為主,可根據不同屬性渲染不同樣式去實現(xiàn)布局和不同格式的按鈕。

本文的表單組件,除了要渲染頁面組件,還支持很好頁面交互,從Element3的表單組件開始。

1 表單組件

Element表單組件 頁面里,可見表單種類的組件類型很多,輸入框、單選框和評分組件等都算表單組件系列。

Element3官方演示表單的Template,整體表單頁面分三層:

  • el-form負責最外層的表單容器

  • el-form-item負責每個輸入項的label和校驗管理

  • el-input或el-switch負責具體的輸入組件


:model="ruleForm"
:rules="rules"
ref="form"
label-width="100px"
class="demo-ruleForm"
>































>立即創(chuàng)建
>
重置

把上面代碼簡化為最簡單形式,只留el-input作輸入項,可清晰看到表單組件工作的模式:

  • el-form組件使用:model提供數據綁定;使用rules提供輸入校驗規(guī)則,規(guī)范用戶的輸入內容

  • el-form-item作為輸入項的容器,對輸入進行校驗,顯示錯誤信息


登錄

rules和model工作流程

用reactive返回用戶輸入的數據,username和passwd輸入項對應,然后rules使用reactive包裹用戶輸入項校驗的配置。

具體校驗規(guī)則,主流用async-validator庫,詳細校驗規(guī)則訪問 async-validator的官網。而表單Ref上額外新增一個validate方法,執(zhí)行所有的校驗邏輯來顯示用戶的報錯信息,下圖即用戶輸入不符合rules配置后,頁面的報錯提示效果。

const ruleForm = reactive ({
username:"",
passwd:""
})

// 1. 定義驗證規(guī)則
const rules = reactive({
rules: {
username: { required: true,min: 1, max: 20, message: '長度在 1 到 20 個字符', trigger: 'blur' },
passwd: [{ required: true, message: '密碼', trigger: 'blur' }]
}
})

function submitForm() {
form.value.validate((valid) => {
if (valid) {
alert('submit!')
} else {
console.log('error submit!!')
return false
}
})
}

表單組件實現(xiàn)

進入src/components目錄,新建Form.vue去實現(xiàn)el-form組件,該組件是整個表單組件的容器,負責管理每一個el-form-item組件的校驗方法,自身還提供一個檢查所有輸入項的validate方法。

如下代碼注冊了傳遞的屬性的格式,并注冊了validate方法使其對外暴露使用:

interface Props {
label?: string
prop?: string
}

const props = withDefaults(defineProps (), {
label: "",
prop: ""
})

const formData = inject(key)

const o: FormItem = {
validate,
}

defineExpose(o)

在 el-form 組件中咋管理el-form-item組件?

新建FormItem.vue文件,該組件加載完畢后去通知el-form組件自己加載完畢,在el-form中就可使用數組管理所有內部的form-item組件。

import { emitter } from "../../emitter"
const items = ref ([])

emitter.on("addFormItem", (item) => {
items.value.push(item)
})

然后el-form-item還要負責管理內部的input輸入標簽,并且從form組件中獲得配置的rules,通過rules的邏輯,來判斷用戶的輸入值是否合法。

el-form還要管理當前輸入框的label,看看輸入狀態(tài)是否報錯,以及報錯的信息顯示,這是一個承上啟下的組件。

onMounted(() => {
if (props.prop) {
emitter.on("validate", () => {
validate()
})
emitter.emit("addFormItem", o)
}
})
function validate() {
if (formData?.rules === undefined) {
return Promise.resolve({ result: true })
}
const rules = formData.rules[props.prop]
const value = formData.model[props.prop]
const schema = new Schema({ [props.prop]: rules })
return schema.validate({ [props.prop]: value }, (errors) => {
if (errors) {
error.value = errors[0].message || "校驗錯誤"
} else {
error.value = ""
}
})
}

form、form-item和input三組件之間是嵌套使用關系:

  • form提供了所有的數據對象和配置規(guī)則

  • input負責具體的輸入交互

  • form-item負責中間的數據和規(guī)則管理及顯示具體的報錯信息

這就需要一個強有力的組件通信機制,Vue的

組件之間的通信父子組件通信

通過props和emits來通信。父元素通過props把需要的數據傳遞給子元素,子元素通過emits通知父元素內部的變化,并且還可以通過defineDepose的方式暴露給父元素方法,可以讓父元素調用自己的方法。

form和input組件咋通信?

這種祖先元素和后代元素,中間可能嵌套很多層關系,Vue提供provide、inject API。

在組件中可用provide函數向所有子組件提供數據,子組件內部通過inject注入使用。provide提供的只是普通數據,未做響應式處理,若子組件內部需響應式數據,需在provide函數內部用ref或reative包裹。

prvide和inject的類型系統(tǒng),可用Vue的InjectiveKey聲明。在form目錄下新建type.ts專門管理表單組件用到的相關類型。

如下定義了表單form和表單管理form-item的上下文,并通過InjectionKey管理提供的類型。

import { InjectionKey } from "vue"
import { Rules, Values } from "async-validator"

export type FormData = {
model: Record
rules?: Rules
}

export type FormItem = {
validate: () => Promise
}

export type FormType = {
validate: (cb: (isValid: boolean) => void) => void
}

export const key: InjectionKey = Symbol("form-data")

而如下代碼通過provide向所有子元素提供form組件的上下文。子組件內部通過inject獲取,很多組件都是嵌套成對出現(xiàn)。

provide(key, {
model: props.model,
rules?: props.rules,
})

# 子組件
const formData = inject(key)

input實現(xiàn)邏輯

下面代碼,input 的核心邏輯就是對v-model支持。

v-mode是:mode-value="x"和@update:modelValute兩個寫法簡寫,組件內部獲取對應的屬性和modelValue方法即可。

需關注的代碼是我們輸入完成之后的事件,輸入的結果校驗是由父組件el-form-item來實現(xiàn)的,只需通過emit對外廣播。

class="el-form-item"
>

v-if="label"
>{{ label }}


v-if="error"
class="error"
>
{{ error }}



點擊按鈕時,在最外層的form標簽內部會對所有的輸入項進行校驗。由于我們管理著所有的form-item,只需要遍歷所有的form-item,依次執(zhí)行即可。

下面的代碼就是表單注冊的validate方法,我們遍歷全部的表單輸入項,調用表單輸入項的validate方法,有任何一個輸入項有報錯信息,整體的校驗就會是失敗狀態(tài)。

function validate(cb: (isValid: boolean) => void) {
const tasks = items.value.map((item) => item.validate())
Promise.all(tasks)
.then(() => { cb(true) })
.catch(() => { cb(false) })
}

上面代碼實際執(zhí)行的是每個表單輸入項內部的validate方法,這里我們使用的就是async-validate的校驗函數。在validate函數內部,我們會獲取表單所有的ruls,并且過濾出當前輸入項匹配的輸入校驗規(guī)則,然后通過AsyncValidator對輸入項進行校驗,把所有的校驗結果放在model對象中。如果errors[0].message非空,就說明校驗失敗,需要顯示對應的錯誤消息,頁面輸入框顯示紅色狀態(tài)。

import Schema from "async-validator"

function validate() {
if (formData?.rules === undefined) {
return Promise.resolve({ result: true })
}
const rules = formData.rules[props.prop]
const value = formData.model[props.prop]
const schema = new Schema({ [props.prop]: rules })
return schema.validate({ [props.prop]: value }, (errors) => {
if (errors) {
error.value = errors[0].message || "校驗錯誤"
} else {
error.value = ""
}
})
}

總結

本文設計實現(xiàn)了復雜的組件類型——表單組件。在組件庫中作用,就是收集和獲取用戶的輸入值,并提供用戶的輸入校驗,如輸入長度、郵箱格式等,符合校驗規(guī)則后,就可獲取用戶輸入內容,提交給后端。

要實現(xiàn)三類組件:

  • el-form提供表單的容器組件,負責全局的輸入對象model和校驗規(guī)則rules的配置,在用戶點擊提交時,可執(zhí)行全部輸入項的校驗規(guī)則

  • input類組件,輸入內容的輸入框、下拉框、滑塊等都屬這類。主要負責顯示對應的交互組件,并且監(jiān)聽所有的輸入項,用戶在交互的同時通知執(zhí)行校驗

  • 介于form和input中間的form-item組件,負責每一個具體輸入的管理,從form組件中獲取校驗規(guī)則,從input中獲取用戶輸入的內容,通過async-validator校驗輸入是否合法后顯示對應的輸入狀態(tài),并且還能把校驗方法提供給form組件,form可很方便地管理所有form-item。

組件設計需考慮:

  • 內部交互邏輯

  • 對子組件提供什么數據

  • 對父組件提供什么方法

  • 需不需要通過provide或inject來進行跨組件通信等

表單驗證流程

1. 定義驗證規(guī)則

const rules = reactive({
username: [
{ required: true, message: '請輸入用戶名', trigger: 'blur' },
{ min: 3, max: 20, message: '長度在 3 到 20 個字符', trigger: 'blur' },
{ validator: validateUsername, trigger: 'blur' }
],
password: [
{ required: true, message: '請輸入密碼', trigger: 'blur' },
{ min: 6, max: 20, message: '長度在 6 到 20 個字符', trigger: 'blur' }
]
})

2. 綁定規(guī)則到表單

:model="loginForm"
:rules="rules"
ref="loginFormRef"
>

3. 自定義驗證方法

async function validateUsername(rule, value, callback) {
if (value === '') {
callback(new Error('請輸入用戶名'))
} else {
callback() // 驗證通過
}
}

4. 觸發(fā)驗證

const login = async () => {
if (!loginFormRef.value) return

try {
// 觸發(fā)表單驗證
const valid = await loginFormRef.value.validate()
if (valid) {
// 驗證通過,執(zhí)行登錄
await doLogin()
}
} catch (error) {
// 驗證失敗處理
handleError(error)
}
}

驗證規(guī)則說明:

  • required: 必填項

  • min/max: 長度限制

  • trigger: 觸發(fā)方式(blur/change)

  • validator: 自定義驗證方法

  • message: 錯誤提示信息

驗證流程:

  1. 用戶輸入觸發(fā)驗證

  2. 執(zhí)行驗證規(guī)則檢查

  3. 顯示錯誤提示(如果有)

  4. 驗證通過則提交表單

類比 Java:

  • 類似@Valid注解驗證

  • 類似 JSR-303 驗證規(guī)則

  • 類似 BindingResult 結果處理

FAQ

Q:表單組件設計上能否通過Vue 2流行的event-bus實現(xiàn)?

A:Vue 2 時代,event-bus(事件總線)是一個較為流行的解決組件通信的方式。通過在全局創(chuàng)建一個 Vue 實例作為事件總線,子組件可以通過$emit觸發(fā)事件,父組件通過$on監(jiān)聽事件,從而實現(xiàn)跨組件的通信。

對于本例中的表單組件,理論上可以通過event-bus來實現(xiàn)組件之間的通信,但從現(xiàn)代 Vue 的架構和最佳實踐來看,這種方式已經不推薦,主要原因包括以下幾點:

1. 可維護性差

  • 問題event-bus是一種松散的事件驅動通信方式,依賴于事件的觸發(fā)和監(jiān)聽,但事件本身沒有強類型約束或明確的調用鏈,難以調試和維護。

  • 改進:Vue 3 的provide/inject或者 Vuex/Pinia 等狀態(tài)管理工具,可以更清晰地定義數據流和邏輯職責。

2. 性能問題
  • 問題:使用event-bus可能導致事件在全局廣播,尤其在大型項目中,大量事件會增加性能開銷。

  • 改進:本例中,通過provide/inject實現(xiàn)的數據共享僅限于組件樹中的父子組件或兄弟組件之間,數據傳遞范圍清晰且高效。

3. 復雜性控制
  • 問題event-bus的事件管理隨著項目復雜度增加會導致難以跟蹤。例如,在表單校驗中,需管理每個form-item的校驗狀態(tài)并與form同步,如果使用event-bus,需要手動處理事件的訂閱與銷毀。

  • 改進:本例中,使用 Vue 的生命周期鉤子(如onMountedonUnmounted)配合provide/inject機制,自動管理組件的注冊和銷毀邏輯,代碼更加直觀。

4. 與現(xiàn)代 Vue 設計理念不符
  • 問題event-bus屬于 Vue 2 時代的過渡方案,而 Vue 3 的 Composition API 提供了更優(yōu)雅的通信機制(如響應式reactive、ref數據,以及組合函數)。

  • 改進:在本例中,provide/inject結合響應式數據實現(xiàn)了父組件與子組件的通信,使代碼風格更加符合現(xiàn)代 Vue 的聲明式設計思想。

總結

雖然event-bus可以實現(xiàn)類似的功能,但它在代碼結構、性能和可維護性上都存在明顯的缺陷,已經逐漸被 Vue 3 的現(xiàn)代通信機制所取代。對于表單組件這種較為復雜的場景,推薦使用provide/inject結合響應式數據的方式來管理組件通信,以提高代碼的健壯性和可擴展性。

關注我,緊跟本系列專欄文章,咱們下篇再續(xù)!

★ 作者簡介:魔都架構師,多家大廠后端一線研發(fā)經驗,在分布式系統(tǒng)設計、數據平臺架構和AI應用開發(fā)等領域都有豐富實踐經驗。 各大技術社區(qū)頭部專家博主。具有豐富的引領團隊經驗,深厚業(yè)務架構和解決方案的積累。 負責: 中央/分銷預訂系統(tǒng)性能優(yōu)化 活動&券等營銷中臺建設 交易平臺及數據中臺等架構和開發(fā)設計 車聯(lián)網核心平臺-物聯(lián)網連接平臺、大數據平臺架構設計及優(yōu)化 LLM Agent應用開發(fā) 區(qū)塊鏈應用開發(fā) 大數據開發(fā)挖掘經驗 推薦系統(tǒng)項目 目前主攻市級軟件項目設計、構建服務全社會的應用系統(tǒng)。 ”

參考:

  • 編程嚴選網

編程嚴選網:http://www.javaedge.cn/ 專注分享軟件開發(fā)全生態(tài)相關技術文章、視頻教程資源、熱點資訊等,全站資源免費學習,快來看看吧~ 【編程嚴選】星球

歡迎長按圖片加好友,我會第一時間和你分享軟件行業(yè)趨勢,面試資源,學習方法等等。

添加好友備注【技術群交流】拉你進技術交流群

關注公眾號后,在后臺私信:

  • 更多教程資源應有盡有,歡迎關注并加技術交流群,慢慢獲取

  • 為避免大量資源被收藏白嫖而浪費各自精力,以上資源領取分別需要收取1元門檻費!


特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關推薦
熱點推薦
留幾手為閆學晶叫屈?稱抖音用戶都自卑又敏感,評論區(qū)炸鍋了

留幾手為閆學晶叫屈?稱抖音用戶都自卑又敏感,評論區(qū)炸鍋了

小徐講八卦
2026-01-11 16:10:03
華為新機突然上架:1月9日,新品上市

華為新機突然上架:1月9日,新品上市

科技堡壘
2026-01-09 11:42:36
反制開始!星鏈兩次威脅中國空間站后,我國新增20萬顆衛(wèi)星申請!

反制開始!星鏈兩次威脅中國空間站后,我國新增20萬顆衛(wèi)星申請!

Kerry哲學
2026-01-11 09:20:56
WTT冠軍賽:女單決賽席位出爐!朱雨玲4:2削球手,完成十年之約

WTT冠軍賽:女單決賽席位出爐!朱雨玲4:2削球手,完成十年之約

國乒二三事
2026-01-11 18:04:49
韓國某中學把“中華人民共和國”當作班級目標引爭議

韓國某中學把“中華人民共和國”當作班級目標引爭議

隨波蕩漾的漂流瓶
2026-01-10 17:50:06
做最壞打算!中國055大驅第二批加速,美媒:還有被美軍扣船隱憂

做最壞打算!中國055大驅第二批加速,美媒:還有被美軍扣船隱憂

諦聽骨語本尊
2026-01-09 19:26:20
頭號內鬼被捕,關閉防空系統(tǒng)出賣馬杜羅坐標,5000萬沒拿到就栽了

頭號內鬼被捕,關閉防空系統(tǒng)出賣馬杜羅坐標,5000萬沒拿到就栽了

新沖浪青年
2026-01-10 20:30:14
隨著卡塔爾0-1,伊朗0-0,亞洲杯最新積分榜出爐:中國男足倒數第二

隨著卡塔爾0-1,伊朗0-0,亞洲杯最新積分榜出爐:中國男足倒數第二

側身凌空斬
2026-01-11 02:40:58
霍啟剛突然公示財產!35套物業(yè)曝光,28套出租,這才是真豪門格局

霍啟剛突然公示財產!35套物業(yè)曝光,28套出租,這才是真豪門格局

行者聊官
2026-01-10 20:42:35
WTT多哈冠軍賽:6號種子朱雨玲4-2晉級,韓瑩雖敗猶榮

WTT多哈冠軍賽:6號種子朱雨玲4-2晉級,韓瑩雖敗猶榮

余蹮搞笑段子
2026-01-11 18:25:11
這反轉驚掉下巴!當初要整蔡正元的檢察官陳舒怡,覺都睡不踏實了

這反轉驚掉下巴!當初要整蔡正元的檢察官陳舒怡,覺都睡不踏實了

扶蘇聊歷史
2026-01-10 12:05:03
301005,商業(yè)航天十倍大牛股!節(jié)后機構緊急調研股曝光

301005,商業(yè)航天十倍大牛股!節(jié)后機構緊急調研股曝光

數據寶
2026-01-11 07:34:07
太解氣了,2026殯葬新規(guī)要來了,以后辦白事再也不用當"冤大頭"了

太解氣了,2026殯葬新規(guī)要來了,以后辦白事再也不用當"冤大頭"了

知鑒明史
2026-01-11 10:35:03
日本人的祖先究竟是誰?美國教授拿出DNA,日本人懵了

日本人的祖先究竟是誰?美國教授拿出DNA,日本人懵了

馬探解說體育
2026-01-09 18:22:53
日本拉面店禁止中國人入內!韓國網友揭露內幕并呼吁:我們也不能去!

日本拉面店禁止中國人入內!韓國網友揭露內幕并呼吁:我們也不能去!

奮斗在韓國
2026-01-10 14:03:22
60年一遇!今年春節(jié)不用穿棉襖了?最冷時段,已經確定!

60年一遇!今年春節(jié)不用穿棉襖了?最冷時段,已經確定!

老特有話說
2026-01-10 15:37:26
金價飆升,多家銀行公告提醒

金價飆升,多家銀行公告提醒

澎湃新聞
2026-01-11 14:00:03
3比0橫掃張本智和!19歲新星勒布倫進攻犀利無人能擋

3比0橫掃張本智和!19歲新星勒布倫進攻犀利無人能擋

卿子書
2026-01-11 09:37:34
突發(fā)!山東一地120調度員集中離職!4人已離職、2人提出辭職……

突發(fā)!山東一地120調度員集中離職!4人已離職、2人提出辭職……

醫(yī)脈圈
2026-01-11 12:16:08
吳石案終極潛伏者隱姓 42 年,晚年返大陸熱淚盈眶

吳石案終極潛伏者隱姓 42 年,晚年返大陸熱淚盈眶

嘮叨說歷史
2026-01-07 12:42:21
2026-01-11 19:55:00
JavaEdge incentive-icons
JavaEdge
Java 技術
466文章數 457關注度
往期回顧 全部

科技要聞

“我們與美國的差距也許還在拉大”

頭條要聞

小學生留遺書在家中服藥自殺 母親起訴學校和英語老師

頭條要聞

小學生留遺書在家中服藥自殺 母親起訴學校和英語老師

體育要聞

詹皇曬照不滿打手沒哨 裁判報告最后兩分鐘無誤判

娛樂要聞

留幾手為閆學晶叫屈?稱網友自卑敏感

財經要聞

外賣平臺"燒錢搶存量市場"迎來終局?

汽車要聞

2026款宋Pro DM-i長續(xù)航補貼后9.98萬起

態(tài)度原創(chuàng)

家居
房產
教育
手機
軍事航空

家居要聞

木色留白 演繹現(xiàn)代自由

房產要聞

66萬方!4755套!三亞巨量房源正瘋狂砸出!

教育要聞

李希貴:下一代學校應該什么樣?

手機要聞

消息稱三星Galaxy S26系列手機將首次提供2400萬像素切換開關

軍事要聞

俄大使:馬杜羅夫婦被控制時身邊沒人

無障礙瀏覽 進入關懷版