在開發(fā)過程中有一個可以讓客戶自己來設(shè)計表單的需求贞盯,隨后看到了這個FormMaking,這個基于vue和elmenet-ui的一款表單設(shè)計器沪饺,因為網(wǎng)上使用的較少躏敢,自己記錄一下,以備有類似問題時好上手整葡!
官網(wǎng):http://docs.form.making.link
// npm 的下載
npm install form-making -S
因為是 element-ui 的組件庫件余,在使用的時候需要引入 Element 包,具體引入方法請參考 Element 文檔 快速上手
// main.js中完全引入,官網(wǎng)有部分引入的方法
import FormMaking from 'form-making'
import 'form-making/dist/FormMaking.css'
Vue.use(FormMaking)
// index.html中引入ace.js啼器,可以預(yù)覽生成的json或html旬渠,如果不引也可以生成,但沒有解析格式樣式端壳。
<!-- 需要在設(shè)計器中預(yù)覽代碼需要引入ace.js庫 -->
<script src="https://unpkg.com/form-making/public/lib/ace/ace.js"></script>
ace.js是在線訪問的告丢,因為項目原因沒辦法訪問網(wǎng)絡(luò),于是按照地址將ace.js下載到本地损谦,引入后發(fā)現(xiàn)運行時會提示報缺少其它訪問的js及html的文件(就是在文章頂部動圖中所看到的報錯)岖免,應(yīng)該是ace.js內(nèi)部又訪問了其它的文件,為了彌補報錯提示及展示效果成翩,可將提示缺少的文件進行下載觅捆,在官網(wǎng)進入設(shè)計器頁面中的NetWork中進行獲取
將需要的文件與ace.js一起放在static靜態(tài)文件夾中一起引入。
補漏一個mode-html.js麻敌,位置和方法與上面的三個相同 =。=掂摔!
文件提取地址:https://pan.baidu.com/s/1anhH7lqY8QCx1CORMg0zgA
提取密碼:1ybl
快速上手:
表單設(shè)計器
// 全局使用术羔,使用時需要設(shè)置設(shè)計器的高度,默認情況高度是根據(jù)父元素 100% 來渲染
<template>
<fm-making-form
ref="makingform"
style="height: 100vh"
preview
generate-code
generate-json
>
<template slot="action">
</template>
</fm-making-form>
</template>
表單生成器
// 可以將設(shè)計器中生成的json拿到想展示的頁面乙漓,就可以將頁面進行展示
<template>
<div>
<fm-generate-form
:data="jsonData"
ref="generateForm"
>
</fm-generate-form>
<el-button type="primary" @click="handleSubmit">Submit</el-button>
</div>
</template>
export default {
data () {
return {
jsonData: {"list":[{"type":"input","icon":"icon-input","options":{"width":"100%","defaultValue":"","required":false,"dataType":"string","pattern":"","placeholder":"","customClass":"","disabled":false,"labelWidth":100,"isLabelWidth":false,"hidden":false,"dataBind":true,"showPassword":false,"remoteFunc":"func_1575897887618","remoteOption":"option_1575897887618"},"name":"單行文本","key":"1575897887618","model":"input_1575897887618","rules":[{"type":"string","message":"單行文本格式不正確"}]}],"config":{"labelWidth":100,"labelPosition":"right","size":"small","customClass":""}},
}
},
methods: {
handleSubmit () {
this.$refs.generateForm.getData().then(data => {
alert(JSON.stringify(data))
}).catch(e => {
})
}
}
}
動態(tài)數(shù)據(jù)
// element-ui彈窗中展示表單
<el-dialog title="表單" :visible.sync="true" width="50%">
<fm-generate-form
:data="jsonData"
ref="generateForm"
>
</fm-generate-form>
<el-button type="primary" @click="handleSubmit">確定</el-button>
</el-dialog>
export default {
data () {
return {
// valueData中可以獲取接口返回的數(shù)據(jù)级历,將對應(yīng)的表單動態(tài)賦值
valueData: {name: '新的單行名稱'}
jsonData: {"list":[{"type":"input","icon":"icon-input","options":{"width":"100%","defaultValue":"","required":false,"dataType":"string","pattern":"","placeholder":"","customClass":"","disabled":false,"labelWidth":100,"isLabelWidth":false,"hidden":false,"dataBind":true,"showPassword":false,"remoteFunc":"func_1575897887618","remoteOption":"option_1575897887618"},"name":"單行文本","key":"1575897887618","model":"input_1575897887618","rules":[{"type":"string","message":"單行文本格式不正確"}]}],"config":{"labelWidth":100,"labelPosition":"right","size":"small","customClass":""}},
}
}
}
在使用時發(fā)現(xiàn)分普通版本和高級版本,在官網(wǎng)的一些API或方法為紅色叭披,則表示為收費的高級版本方可使用寥殖,不過對于簡單的項目來說,普通的版本夠用涩蜘。
操作中使用柵格布局(默認24格)嚼贡,對拖入的基礎(chǔ)字段進行寬度布局調(diào)整,如果底層不使用柵格布局同诫,直接將基礎(chǔ)字段進行拖入粤策,頁面中會自適應(yīng)頁面寬度進行換行,初學(xué)較難控制误窖。
加載表單數(shù)據(jù)時叮盘,將引入數(shù)據(jù)存入:value="" 便可自動渲染表單
<template>
<div>
<fm-generate-form
:data="jsonData"
:value="editData"
ref="generateForm"
>
</fm-generate-form>
</div>
</template>
export default {
data () {
return {
jsonData: {"list":[{"type":"input","icon":"icon-input","options":{"width":"100%","defaultValue":"","required":false,"dataType":"string","pattern":"","placeholder":"","customClass":"","disabled":false,"labelWidth":100,"isLabelWidth":false,"hidden":false,"dataBind":true,"showPassword":false,"remoteFunc":"func_1575897887618","remoteOption":"option_1575897887618"},"name":"名稱","key":"1575897887618","model":"name","rules":[{"type":"string","message":"名稱格式不正確"}]}],"config":{"labelWidth":100,"labelPosition":"right","size":"small","customClass":""}},
editData: {
/* 需要加載的表單數(shù)據(jù)可以在這里進行設(shè)置 */
name: 'Gavin'
},
}
}
}
例:用于配合el-dialog彈窗展示表單使用
formData:設(shè)計表單時所生成的JSON,用于初始表單雛形霹俺。
valueData:渲染表單所需要的數(shù)據(jù)柔吼,用于頁面內(nèi)容的數(shù)據(jù)渲染。
需求:不使用柵格布局丙唧,表單設(shè)計時控制基礎(chǔ)字段的寬度愈魏,表單生成時自適應(yīng)頁面的寬度,默認同一行展示,寬度超出時換行蝌戒。
基礎(chǔ)字段默認是獨占一行串塑,設(shè)置了寬度也只能改變輸入框的寬度,根據(jù)操作組件頁面所發(fā)生的變化北苟,拿到標簽生成的類名桩匪,可能是因為嵌套的原因,樣式局部作用無效
// 表單設(shè)計器的標簽樣式style中添加了
display:flex
// 并且在style標簽中添加
.el-form-item--small {
float: left;
}
// 在表單生成頁同樣在style標簽中設(shè)置了
float: left
// 為的是不管先進入哪個頁面友鼻,都會全局的添加上float傻昙,也可以在全局樣式中添加
上面的方法是在全局中添加了css樣式,但如果項目不斷發(fā)展彩扔,這里很可能就會給以后挖下一個坑妆档。于是將css樣式改成了局部,避免了全局污染
// 表單設(shè)計頁
<template>
<div>
<fm-making-form
ref="makingform"
style="height: 100vh; display: flex"
preview
generate-code
generate-json
>
</fm-making-form>
</div>
</template>
<script>
export default {
data () {
return {
item: {}
}
},
mounted () {
this.item = this.$refs.makingform
},
watch: {
// 監(jiān)聽對象內(nèi)部數(shù)組的變化
'item.widgetForm.list': {
handler() {
// 在這里獲取節(jié)點時虫碉,有一個bug一直沒解決贾惦,于是調(diào)用強刷頁面在updated中進行操作
// bug問題只出現(xiàn)在單行文本字段拖入時,無法獲取到第一個敦捧,如果添加deep: true 深度監(jiān)聽须板,又無法獲取到第二個,其他字段拖入均無問題兢卵。
this.$forceUpdate() // 強制刷新頁面
}
}
},
updated () {
// 強制刷新頁面后习瑰,updated可以獲取到節(jié)點
var smalls = document.getElementsByClassName('el-form-item--small')
for(var i = 0; i < smalls.length; i++) {
smalls[i].style.float = 'left'
}
}
}
</script>
// 表單生成頁
因為頁面的數(shù)據(jù)是動態(tài)生成的,我們要獲取節(jié)點并添加style,不能在mounted里進行操作秽荤,在請求返回數(shù)據(jù)后來執(zhí)行
this.$nextTick(() => {
var smalls = document.getElementsByClassName('el-form-item--small')
for(var i = 0; i < smalls.length; i++) {
smalls[i].style.float = 'left'
}
})
但在設(shè)計表單中發(fā)現(xiàn)甜奄,更改表單屬性,組件的尺寸會影響到class類名的改變窃款,從而無法準確獲取到元素節(jié)點课兄,于是增加了兼容方法,通過判斷尺寸的size, 來決定獲取什么樣的節(jié)點名
表單生成器API的使用
getData 獲取表單數(shù)據(jù) -
reset 重置表單數(shù)據(jù)
this.$refs.formMaking.getData().then(data => {})
this.$refs.formMaking.reset()
官網(wǎng)給出的reset()雁乡,項目中卻沒有達到重置的效果第喳,嘗試了很多的方法,最后給出自己的方法
// 第一種在重新獲取數(shù)據(jù)時踱稍,將formdata的數(shù)據(jù)也重新獲取賦值曲饱,就相當將表格的結(jié)構(gòu)也重新渲染
// 第二種,將valueData使用object的方法將其清空,然后再重新賦值
for(var key in this,valueData) {
this.valueData[key] = ''
}
有使用過的朋友珠月,是否可以指出表單設(shè)計頁中的問題扩淀?!
未結(jié)束啤挎,更多的使用方法持續(xù)更新中...