el-form-renderer使用教程
前言
el-form-renderer是基于element的表單渲染器,動態(tài)渲染,數(shù)據(jù)驅(qū)動
el-form-renderer/README-zh.md at dev · FEMessage/el-form-renderer · GitHub
el-form-renderer是基于 element-ui 封裝的表單渲染器,但不局限于 element-ui 組件。在完整繼承了 element 的form表單屬性的基礎(chǔ)上進行了簡單擴展,一些非表單組件或者封裝的自定義組件,如圖片上傳、富文本等也可進行整合,從而用戶能夠通過使用一段預(yù)設(shè)的數(shù)據(jù)渲染出一個完整的表單。
起步
?# Step1 確認你已經(jīng)正確安裝并使用了 element-ui yarn add @femessage/el-form-renderer
<template> <el-form-renderer :content="content"></el-form-renderer> </template> <script> import ElFormRenderer from '@femessage/el-form-renderer' export default { components: { ElFormRenderer, }, data() { return { content: [], } }, } </script>
使用
支持 el-form 上的所有屬性。
- content:[ObjectArray] 定義表單的內(nèi)容,每一個 Object 代表一個原子表單 el-input, el-select, ...,一切 el-form-item 上的屬性都在此聲明,而對于 el-input 等之上的屬性在 $el 屬性上進行聲明,該 Object 上還存在其他屬性,例如: id, type,label, options可選的,等。還有hidden定義其是否隱藏等屬性
- id: id: string 每一個原子都存在 id,用于存儲該原子的值,不能重復(fù)
- type: string 可以是element提供的所有表單組件類型,如傳入'input',則渲染出'el-input,當type="group"時使用 items內(nèi)依然遵循同一層級的id不重復(fù)的原則
- readonly 只讀的 當 type === 'input' 時展示文本值, 當 type === 'select' 時展示對應(yīng)。 label 對于其他組件等同于 disabled = true
- default: 默認值
- options ({label: string; value?: any}[])具有選擇功能的原子表單可用此定義可選項 select, radio-group, radio-button, checkbox-group, checkbox-button
- hidden 傳入一個方法,并返回 boolean,返回 true 時則隱藏該表單項 * formValue 為當前 form 值,item 為當前表單項的定義
- el 用于定義具體原子表單(如el-input)的屬性,比如定義el-input的placeholder
- component component適用于渲染局部注冊組件和自定義組件,而type適用于帶el-前綴的全局組件
- label 設(shè)置el表單項的標簽
update-form && getFormValue
- update-form 更新表單方法 默認情況下,updateForm 來者不拒,不在表單設(shè)置內(nèi)的值,也可以存儲進去
- getFormValue 默認情況下,通過 updateForm 設(shè)置的所有值都會輸出。 如果只想輸出根據(jù) content 設(shè)置的表單項的值,可傳入 {strict: true}
<template> <div class="update-form"> <el-form-renderer :content="content" inline ref="formRender"> <el-button @click="setValue">更新表單</el-button> <div> <el-button type="primary" @click="getValue(false)">獲取數(shù)據(jù)</el-button> <el-button type="primary" @click="getValue(true)" >獲取數(shù)據(jù)過濾掉字段</el-button > </div> </el-form-renderer> <pre>{{ value }}</pre> </div> </template> <script> export default { name: "update-form", data() { return { value: {}, content: [ { id: "name", type: "input", label: "name", el: { placeholder: "name", }, }, { id: "area", type: "select", label: "area", el: { placeholder: "area", }, options: [ { label: "shanghai", value: "shanghai", }, { label: "beijing", value: "beijing", }, ], }, ], }; }, methods: { getValue(strict) { const value = this.$refs.formRender.getFormValue({ strict }); this.value = value; }, setValue() { this.$refs.formRender.updateForm({ name: "alvin", area: "shanghai", // 設(shè)置冗余字段 extraKey: "extraValue", }); }, }, }; </script>
表單項動態(tài)顯示或隱藏(hidden)
以通過 hidden
控制某一表單項的顯示或隱藏。
<template> <div> <el-form-renderer :content="content"></el-form-renderer> </div> </template> <script> import ElFormRenderer from "@femessage/el-form-renderer"; export default { components: { ElFormRenderer, }, data() { return { content: [ { type: "select", id: "selected", label: "選擇項目", options: [ { label: "項目A", value: "optionA", }, { label: "項目B", value: "optionB", }, ], }, { label: "資料", type: "input", id: "data", el: { placeholder: "項目B的具體內(nèi)容", }, hidden: (form, item) => { return this.hiddenChange(form, item); }, }, ], }; }, methods: { hiddenChange(form, item) { console.log(form); //form 收集的數(shù)據(jù) console.log(item); //觸發(fā)元素 return form.selected !== "optionB"; }, }, }; </script>
表單數(shù)據(jù)聯(lián)動(on)
可以通過 on 來監(jiān)聽 blur , focus 等事件來實現(xiàn)表單聯(lián)動 監(jiān)聽表單項發(fā)出的事件
<template> <div> <el-form-renderer :content="content"></el-form-renderer> </div> </template> <script> import ElFormRenderer from "@femessage/el-form-renderer"; export default { components: { ElFormRenderer, }, data() { return { content: [ { label: "英文名", type: "input", id: "fullName", on: { blur: ([event], updateForm) => { const value = event.target.value; const lastName = value.split(" ")[1]; // 通過空格分割出內(nèi)容 updateForm({ lastName }); // 更新其他表單項 }, }, }, { label: "姓氏", type: "input", id: "lastName", }, ], }; }, }; </script>
輸入/輸出格式化(inputFormat/outputFormat)
拿 日期范圍選擇器 為例,組件輸出的值是一條字符串,但后端接口格式是兩個字段 {startDate, endDate},則此時需要對數(shù)據(jù)進行格式化處理
inputFormat 轉(zhuǎn)換輸入的數(shù)據(jù), 使其變成表單項需要的數(shù)據(jù)格式
<template> <el-form-renderer :content="content" ref="form" /> </template> <script> export default { data() { return { content: [ { el: { type: 'daterange', placeholder: '選擇日期', valueFormat: 'yyyy-MM-dd' }, type: 'date-picker', id: 'date', label: '日期', // 接口設(shè)計的時間范圍是兩個字段 '2019-07-23','2019-07-24' // 處理后的值為 [ '2019-07-23', '2019-07-24' ] inputFormat: row => ([row.startDate, row.endDate]) } ] } } } </script>
outputFormat 轉(zhuǎn)換輸出的數(shù)據(jù), 使其變成需要的(接口期望的)數(shù)據(jù)格式
<script> export default { data() { return { content: [ { el: { type: 'daterange', placeholder: '選擇日期', valueFormat: 'yyyy-MM-dd' }, type: 'date-picker', id: 'date', label: '日期', // 處理前的值為 date: [ '2019-07-23', '2019-07-24' ] // 處理后的值為 {startDate: '2019-07-23', endDate: '2019-07-24'} outputFormat: val => { if (!val) { return {startDate: '', endDate: ''} } return { startDate: val[0], endDate: val[1] } } } ] } } } </script>
set-options
使用setOptions更新選擇選項
<template> <el-form-renderer ref="form" :content="content" inline> <el-button @click="setOptions">更新options</el-button> </el-form-renderer> </template> <script> export default { name: "select-demo", data() { return { content: [ { id: "area", type: "select", label: "select", el: { placeholder: "select", }, options: [ { label: "shanghai", value: "shanghai", }, { label: "beijing", value: "beijing", }, ], }, ], }; }, methods: { setOptions() { this.$refs.form.setOptions("area", [ { label: "guangzhou", value: "guangzhou", }, { label: "hangzhou", value: "hangzhou", }, ]); }, }, }; </script>
el-form-renderer 實踐案例
案例一
A 系統(tǒng)有一個解析簡歷的功能,后端接口只能解析電話、郵箱,也即接口只返回 phone、email 兩個字段。后來接口更新了,支持解析姓名:
后端:簡歷解析接口更新了,現(xiàn)在會返回多一個字段 name,你前端那邊也更新一下吧。 前端:您隨便加,接口直接更新就行了,前端不用改。 后端:這么神奇的嗎?這是怎么做到的?
那么前端是如何做到接口返回多一個字段,自己卻不用修改代碼的呢?
分析
原因在于使用了 el-form-renderer 使用了 updateForm 來更新表單值。 updateForm 方法接受一個對象,只要傳入對象的 key 與表單的 id 對應(yīng)上即可更新數(shù)據(jù)。代碼片段如下:
<template> <el-form-renderer :content="content" ref="form" /> </template> <script> export default { data() { return { content: [ { type: 'input', id: 'name', label: '名稱' }, { type: 'input', id: 'phone', label: '電話' }, { type: 'input', id: 'email', label: '郵箱' }, // ... ], } }, methods: { async fetch() { const data = await fetchData() // data: Object // data 中返回多了一個字段 name,也不需要修改代碼 this.$refs.form.updateForm(data) } } } </script>
所以,即使后端豐富了這個 data ,前端也可以“照吃不誤”
如果直接使用 el-form 則無法完成這種操作:你需要手動去更新每個與 el-form-item 綁定的 data 值
<template> <el-form ref="form" :model="form"> <el-form-item label="名稱"> <el-input v-model="form.name"></el-input> </el-form-item> </el-form> </template> <script> export default { data() { return { form: { // 每一個表單項需要主動綁定 name: '', phone: '', email: '', }, } }, methods: { async fetch() { const {name} = await fetchData() // data: Object this.form.phone = data.phone this.form.email = data.email // data 中返回多了一個字段 name,需要多寫下面一行代碼 this.form.name = name } } } </script>
案例二
場景
B 系統(tǒng)的表單頁面比較多,其中不乏帶有復(fù)雜組件的表單,如下圖紅框片所示:
直接使用 el-form 開擼,整個頁面耦合在一起代碼超過 1000 行。
使用 el-form-renderer 后,通過拆分組件,整個頁面代碼量在 300 行左右,業(yè)務(wù)組件代碼量在 100~300 行之間。
明顯能感覺到頁面簡潔了許多,維護性大大提高。
那么,el-rorm-renderer 是怎么做到精簡主頁面代碼的呢?
分析
秘訣在于 el-form-renderer 支持通過 component 屬性渲染自定義組件、在組件內(nèi)部定義檢驗規(guī)則,提高了拆分頁面的可能性。
下面代碼示例中,把選擇優(yōu)惠券的表格,抽離成了一個單獨的組件。
<!--表單主頁面--> <template> <el-form-renderer :content="content" ref="form" /> </template> <script> import SelectTableList from './select-table-list.vue' export default { data() { return { content: [ // ... { id: 'selectedCoupon', // 渲染自定義 table 組件 component: SelectTableList, label: '選擇優(yōu)惠券' }, // ... ], } } } </script>
下面是自定義 table 組件示例代碼。
<!--自定義 table 組件示例代碼--> <template> <div class="select-table-list"> <el-button type="primary" size="small" @click="visible = true">選擇</el-button> <el-table :data="selectedList" border></el-table> <!-- 省略一些代碼 --> </div> </template> <script> export default { name: 'select-table-list', // 自定義校驗規(guī)則 rules: [ { required: true, message: '自定義組件的提醒消息' } ], props: ['value'], data() { return { visible: false, selectedList: [] } }, methods: { confirm() { const selectedVal = 'table選中的值' // 更新 value 值,這樣 el-form-renderer 可以通過 getFormValue() 拿到該值 this.$emit('input', selectedVal) this.visible = false } } } </script>
自定義組件接入指南
el-form-renderer 的 type
有限, 默認只能渲染普通的表單項, 假如現(xiàn)在要渲染一個上傳組件, type
就不夠用了, 那怎么辦呢? 這時候 component 選項就派上用場了
本文將介紹如何開發(fā)符合 el-form-renderer 接入標準的自定義組件, 實現(xiàn)對自定義組件的渲染
自定義組件接入的關(guān)鍵是在組件內(nèi)部實現(xiàn) v-model
建議在自定義組件上綁定 $attrs 和 $listeners
el-form-renderer 對 v-model 的要求是:
有一個 props 為 value對外觸發(fā) input 事件
<template> <el-form-renderer :content="content" /> </template> <script> import MyInput from "@/components/my-input.vue"; export default { data() { return { content: [ { component: MyInput, id: "myInput", label: "label", // 傳入組件屬性 el: { placeholder: "請輸入一個 title", // type: "submit", // submit button title: "這是一個標題", // custom defined props }, // 傳入組件事件 on: { focus: ([event], updateForm) => { console.log(event.target.value); // output: input value }, customEvent: ([value, msg], updateForm) => { console.log(msg); // output: 'message' }, }, }, { id: "document", type: "input", el: { type: "textarea", }, }, ], }; }, }; </script>
<template> <div> <!-- 自定義組件 my-input --> <el-input :value="value" @input="onInput" v-bind="$attrs" v-on="$listeners" /> </div> </template> <script> export default { props: { value: String, title: String, }, watch: { value(value) { this.$emit("customEvent", value, "message"); }, }, methods: { onInput(val) { this.$emit("input", "my-input: " + val); }, }, }; </script>
需要注意,on 中的 function 定義,組件 emit 事件的 payload 將以「數(shù)組」的方式,回調(diào)到第一個參數(shù)
第二個參數(shù)為 updateForm 方法
到此這篇關(guān)于el-form-renderer使用教程的文章就介紹到這了,更多相關(guān)el-form-renderer使用 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VUE?Element修改el-input和el-select長度的具體步驟
這篇文章主要給大家介紹了關(guān)于VUE?Element修改el-input和el-select長度的具體步驟,文中通過代碼介紹的非常詳細,對大家學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-12-12三步搞定:Vue.js調(diào)用Android原生操作
這篇文章主要介紹了三步搞定:Vue.js調(diào)用Android原生操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09Vue 實現(xiàn)分頁與輸入框關(guān)鍵字篩選功能
這篇文章主要介紹了Vue 實現(xiàn)分頁+輸入框關(guān)鍵字篩選功能,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-01-01vue?parseHTML?函數(shù)拿到返回值后的處理源碼解析
這篇文章主要為大家介紹了vue?parseHTML?函數(shù)拿到返回值后的處理源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07vue自定v-model實現(xiàn)表單數(shù)據(jù)雙向綁定問題
vue.js的一大功能便是實現(xiàn)數(shù)據(jù)的雙向綁定。這篇文章主要介紹了vue自定v-model實現(xiàn) 表單數(shù)據(jù)雙向綁定的相關(guān)知識,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-09-09