需求:怎样快速的生成表单,不用每次都去拷贝粘贴
思路:用过antd或者iView框架的都知道,参考table组件,给出一个Column和dataSource通过遍历循环的方式去生成表格,同样是否也可以给出一个2个参数去生成一个表单呢?答案显而易见是可行的,于是我写了一个FormMain的组件用来快捷是生成表单
代码如下
// FormMain.vue
<script type="text/jsx">
function noop() {}
let id = 0
export default {
name: 'FnFormMain',
props: {
asyncProps: Object,
data: {
type: Object,
default: () => { return {} }
},
config: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {
dictionaryData: {
},
propsAttar: {}
}
},
computed: {
},
created() {
let arr = ['select', 'radio', 'checkbox']
this.config.map(el => {
let isArray = Array.isArray(el)
if (isArray) {
el.map(l => {
if (arr.indexOf(l.type) >= 0) {
this.setProps(l)
}
})
} else if (arr.indexOf(el.type) >= 0) {
this.setProps(el)
}
})
},
methods: {
remoteMethod() {
debugger
},
handleAvatarSuccess(url, file, key) {
this.data[key] = url
this.onUploadSuccess(url, file)
},
beforeUploadFile(file) {
this.beforeUpload(file)
},
setProps(el) {
let { async, key, data = [] } = el
if (async) {
this.$set(this.propsAttar, key, [])
async(key).then(res => {
el.data = this.propsAttar[key] = res
})
} else {
el.data = this.propsAttar[key] = typeof data === 'string' ? this.dictionaryData[data] : data
}
},
formatHtml(el, key, createElement) {
let relust
let { disabled } = el
let isDisabled = disabled ? disabled.value === undefined ? !!this.data[disabled.key] : this.data[disabled.key] === disabled.value : false
switch (el.type) {
case 'select':
if (el.data || this.propsAttar[key]) {
if (!el.data) {
relust = ''
return
}
relust = (
<el-select disabled={isDisabled} multiple={el.multiple} allow-create={el.allowCreate} default-first-option remote={el.remote} remote-method={(value) => {
el.remoteMethod(value, el)
}} clearable filterable={el.filterable} v-model={this.data[key]} placeholder={`请选择${el.label}`}>
{
el.group
? el.data.map(e =>
<el-option-group label={e.label} key={e.value}>
{
e.children.map(subEl => <el-option label={subEl.label} value={subEl.value}> </el-option>)
}
</el-option-group>
)
: el.data.map(subEl => <el-option label={subEl.label} value={subEl.value}></el-option>)
}
</el-select>
)
} else {
relust = '字段数据不存在'
}
break
case 'input':
relust = (
<el-input placeholder={`请输入${el.label}`} v-model={this.data[key]}></el-input>
)
break
default:
break
}
return relust
}
},
render(createElement) {
const component = (
<div>
{
this.config.map(el => {
let isArray = Array.isArray(el)
let { key, labelWidth, label, show } = isArray ? el[0] : el
let relust = ''
if (isArray && (el[0] && el[0].col)) {
relust = []
el.forEach((item, index) => {
let { key, labelWidth, label, show } = item
relust.push(
<el-col span={12}>
<el-form-item v-show={show ? (this.data[show.key] === show.value) : true} label-width={labelWidth} prop={key} label={ labelWidth === undefined || labelWidth !== '0' ? label : '' }>
{
this.formatHtml(item, item.key, createElement)
}
</el-form-item>
</el-col>
)
})
return (
<el-row gutter={10}>
{relust}
</el-row>
)
} else if (isArray) {
relust = []
let len = el.length
el.forEach((item, index) => {
relust.push(
<el-col span={11}>
{
this.formatHtml(item, item.key, createElement)
}
</el-col>
)
if (index < len - 1) {
relust.push(
<el-col class="text-center" span={2}> - </el-col>
)
}
})
} else {
relust = this.formatHtml(el, key, createElement)
}
return (
<el-form-item v-show={show ? Array.isArray(show) ? show.reduce((a, b) => { return a && this.data[b.key] === b.value }, true) : (this.data[show.key] === show.value) : true} label-width={labelWidth} prop={key} label={ labelWidth === undefined || labelWidth !== '0' ? label : '' }>
{relust}
</el-form-item>
)
})
}
</div>
)
return component
},
watch: {
}
}
</script>
// template
<div id="app">
<el-form ref="form" :model="data" style="width: 460px;" label-width="80px">
<FormMain :config="config" :data="data"></FormMain>
</el-form>
</div>
import FormMain from "./components/FormMain";
export default {
name: "App",
components: { FormMain },
data() {
return {
config: [
{ label: "A", type: "input", key: "a", labelWidth: "80px" },
{
label: "BB", type: "radio",
key: "d",
data: [ { label: "x", value: 1 },
{ label: "y", value: 2 },
{ label: "z", value: 3 }
]
},
{
label: "B",
type: "select",
key: "b",
async: this.asyncData
},
{ label: "C", tip: "这是C", type: "input", key: "c" },
[
{
label: "日期范围",
type: "date",
key: "beginDate",
tip: "结束时间没有填写则以最近天数为准,填写结束时间则最近天数失效"
},
{ label: "结束日期", type: "date", key: "endDate" }
]
],
data: {
a: 1,
b: 2,
c: 3,
d: 1,
beginDate: new Date(),
endDate: new Date()
}
};
},
methods: {
asyncData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([
{ label: "A", value: 1 },
{ label: "B", value: 2 },
{ label: "C", value: 3 }
]);
}, 1000);
});
}
}
};
支持:
- select radio,checkbox异步请求数据
- label提示信息
- 一列多个输入框
- 指定label宽度
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。