基于vue通用表單解決方案的思考與分析
前言
“那要怎么改?”,“那得改到什么時候?”,“什么時候才能支持這些功能?”。
再一次聽到了這樣的話,我沉默了。到底要怎樣改,這也是我所思考的,最近一直忙于其他,已經有一段時間沒有處理 issue 了,趁著調休,我也要好好思考下。
半年前,接觸了 el-form-renderer ,瞬間感覺減輕了大部分表單編寫的工作,一個簡單的JSON配置,立刻展現(xiàn)出一個功能完好的表單頁面。然而,隨著使用的頻率增加,卻慢慢開始暴露各種不足,該組件的作者也不再單獨對該組件進行維護了。由于項目表單場景的需要,我們 fork 了一個版本,但后來發(fā)現(xiàn)我們更想要的是一套屬于我們自己的表單渲染規(guī)則,于是在我們的 Github 組織下建立了屬于我們的代碼倉庫 @femessage/el-form-renderer (以下都稱為 el-form-renderer ),并開始了我們自己維護之路。
3W
el-form-renderer 是什么?為什么?怎么樣?通過3W分析來看看我們做了什么。
WHAT?
基于 element-ui 封裝的 表單渲染器 ,但不僅僅是 element-ui ,甚至不僅僅是表單。

WHY?
這里的為什么有兩層,第一層是為什么需要表單渲染器?第二次是什么是 el-form-renderer ?
借用《NoForm - 一個更好的表單解決方案》中的一句話:
做 B類業(yè)務 的同學應該深有感觸,我們日常需要面對大量操作類或者表單類的場景,因此只要是能從這些重復的CRUD解放出來的方案,就是最好的方案
我們的目的也很簡單,讓天下沒有難做的表單。
至于為什么是 el-form-renderer ,理由很簡單,我們正在讓沒有難做的表單變成現(xiàn)實,至少在目前數(shù)十個項目中,解決了70%以上的表單方面的需求。
HOW?
如上文所說,如下圖所見:

一個好的表單需要解決的問題:
•表單的取值、賦值、校驗
•表單聯(lián)動
•自定義表單項
•表單項的事件、屬性、slot
•對用戶足夠友好
所謂”下層基礎決定上層建筑“,我們沒有執(zhí)著于從0開始,而是“讓專業(yè)的人做專業(yè)的事”?;A組件, element-ui 足夠專業(yè),也正因為它的專業(yè)性,才讓 el-form-renderer 最初的版本有了用武之地。然而目前遠遠不夠的是,我們沒有很好的處理表單聯(lián)動和表單項的事件、slot的問題,這也正是我所要思考的地方。
基礎用法
先來看看目前我們的實現(xiàn)(更多請參考 文檔 )
<template>
<el-form-renderer label-width="100px" :content="content" />
</template>
<script>
import UploadToAli from '@femessage/upload-to-ali'
export default {
data () {
return {
content: [
{
$id: 'avatar',
label: '頭像',
component: UploadToAli
},
{
$id: 'username',
label: '用戶名',
$type: 'input',
$el: {
placeholder: '請輸入用戶名'
}
}
]
}
}
}
</script>
效果如下:

沒有復雜的邏輯,只需進行簡單配置 JSON 的方式就可實現(xiàn)常用表單功能
解決方案
因為不是從0開始,所以一開始作者的設計只服務于 element-ui 已有的組件。
之前的方案解決了什么
• 表單的取值 getValue ,賦值 updateValue
• 完整繼承了 element 的 form 表單屬性,包括校驗
• 表單聯(lián)動 $enableWhen
大部分簡單的場景已經覆蓋,但是局限于 element-ui 組件,沒有處理好動態(tài)組件選項(如下拉選項)的問題,無法批量賦值,必須手動去空格...
現(xiàn)在的方案優(yōu)化了什么
• 支持自定義組件,擺脫對 element-ui 的完全依賴(仍然依賴它的 el-form , el-form-item )
• 通過 setOptions 方法,動態(tài)的處理組件選項問題
• 添加批量更新數(shù)據(jù)方法 updateForm ,并添加 trim 來處理值
• 為了方便在其他組件中的集成和設置/獲取值的需求,還添加了 inputFormat 、 outputFormat ( issue )
它本已完成了一個華麗的蛻變,甚至成為了我司組件的橋梁地位,然而,面對千奇百怪的需求,它確實還不夠。
存在的問題
目前的7個 issue ,大致可以分為一下幾類:
•表單聯(lián)動
•自定義slot位置
•自定義事件
•其他優(yōu)化
需求告訴我們,它還有很大的進步空間。
思考
回到開始的那些話,面對存在的問題,我們要怎么處理好它。
今天收到一個 PR ,來自公司的一位同事,處理的是 el-form-renderer 中 slot 位置的問題,默認只有 default ,顯示在最后,有需求希望能顯示在指定某一個表單項的前/后。該PR以表單項的 $id 為具名插槽,渲染該插槽內容到對應 $id 表單項的上方。
一個很好的思路,但是也讓我思考了很多,或許它還是沒有達到我的要求。
不妨再思考一個場景,表單的第一項和第三項渲染的上方需要渲染兩個內容相同的 slot ,按上面的思路,我們應該寫兩個template,并分別定義他們要渲染到的位置的的 $id 。
上面的問題并不難解決,定義一個字符串匹配規(guī)則,或者在某一項的配置項中添加要渲染的slot,名字匹配則渲染,以達到復用的目的。
問題似乎是解決了, issue 可以關閉了,但是我們回過頭來想想,我們?yōu)槭裁匆远x slot 位置?
因為有issue,有用戶有這個需求。
那他為什么會有這個需求?
我們不得而知,場景很多,但我們可以大膽的猜測,缺乏一個組件可以滿足他的渲染需求,他需要 slot 來自定義展示內容。
所以,似乎我們需要的并不是 slot ,而是我們缺乏了那些組件,或者我們需要一個更通用的渲染方式來渲染我們的內容。很容易,我們想到了 render ,如果我們返回的是一個 render ,那似乎大部分 issue 可以關閉了。然而事實是,我們從開始就不希望出現(xiàn) render ,因為它一點都不友好,甚至對部分人來說,它不簡單,這不是我們的目的。 我們的目的是為了更好用,更好理解,就向我們的文檔一樣,它很簡單,但很實用 。
許多PR,或者打算提PR的人忽略了一個問題,我們的組件沒有支持事件,它很難實現(xiàn)?不,至少已經實現(xiàn)了綁定屬性,綁定事件并不會多難,但是沒有去支持它,因為我們 思考的是它的必要性 ,表單項是否真的需要綁定事件。
從一開始就說過,不只是 element-ui ,甚至不只是表單。我們的目的不純粹,我們尋找的是通用的方案,如果支持了事件,表單項與業(yè)務代碼的關聯(lián)性絕對會更強,這不是我們希望看到的,至少在我們目前可以看得到的通過可視化的界面生成表單的前提下,我們不希望出現(xiàn)自定義事件的需求,它讓我們通過可視化的界面生成表單變得不那么通用了。
那么,在目前的情況下,真的沒辦法解決這些問題了嗎?答案是否定的。
已知我們可以通過自定義組件的方式拓展我們的表單項,那么我們也可以通過自定義組件解決我們遇到的 issue
import CustomComponent from './custom-component'
export default {
data () {
return {
content: [
{
label: '用戶名',
component: CustomComponent,
$id: 'username',
$el: {
placeholder: '請設置您的登陸用戶名'
}
}
]
}
}
}
或者在一些更簡單的場景
import UploadToAli from './UploadToAli'
export default {
data () {
return {
content: [
{
$id: 'avatar',
label: '圖片',
component: {
data () {
return {
imgUrl: ''
}
},
render: function (h) {
return h(UploadToAli, {
props: {
value: this.imgUrl
},
on: {
input: (val) => {
this.imgUrl = val
this.$emit('input', val)
}
}
}, [
h('p', {
slot: 'spinner'
}, '開始上傳中...')
])
}
}
}
]
}
}
}
如果從這個層面來說,我們早已經解決問題了,但是那些 issue 依然在那兒。還記得之前提過的對用戶足夠友好和 render 的事嗎,目前來看,它能解決問題,但不是一個好的方案,解決問題并沒有那么難,難的是解決了還能足夠友好,足夠簡單,這也是我們一直在努力的方向。
結語
不知不覺寫了好長...
通過配置的方式實現(xiàn)一個表單似乎是一個不錯的思路,目前已經在公司中后臺有過數(shù)十個頁面的嘗試。然而業(yè)務場景千變萬化,我們沒有辦法解決100%的需求,但希望我們的方式為配置性表單能帶來更多的思考。
拋磚引玉,最后貼一次倉庫地址: https://github.com/FEMessage/el-form-renderer ,希望更多的方案和實現(xiàn)浮出水面,解放生產力。再次感謝 原作者
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。
相關文章
vue-quill-editor+plupload富文本編輯器實例詳解
這篇文章主要介紹了vue-quill-editor+plupload富文本編輯器實例詳解,需要的朋友可以參考下2018-10-10
Vue中的ref作用詳解(實現(xiàn)DOM的聯(lián)動操作)
這篇文章主要介紹了Vue中的ref作用詳解(實現(xiàn)DOM的聯(lián)動操作),需要的朋友可以參考下2017-08-08
el-select與el-tree結合使用實現(xiàn)樹形結構多選框
我們在實際開發(fā)中需要用到下拉樹,elementUI是沒有這個組件的,我們就要自己去寫了,下面這篇文章主要給大家介紹了關于el-select與el-tree結合使用實現(xiàn)樹形結構多選框的相關資料,需要的朋友可以參考下2022-10-10

