1、使用方法
表单配置 示例: [{ label: '用户名', // label文字 prop: 'username', // 字段名 element: 'input', // 指定elementui组件 initValue: 'xhcss', // 字段初始值 placeholder: '请输入用户名', // elementui组件属性 rules: [{ required: true, message: '必填项', trigger: 'blur' }], // elementui组件属性 events: { // elementui组件方法 input (val) { console.log(val) }, ...... // 可添加任意elementui组件支持的方法 } ...... // 可添加任意elementui组件支持的属性 }]
2、详细代码使用
比如,我们下拉的话,有时候需要获取数据再生成,但是我们的搜索的话,是一起传入的,可能我技术菜吧!无法实时更新到子集!所以采用了另外一种办法!
具体看注释
<template> <div class="x-search"> <search-form :form-options="searchData" @onSearch="onSearch" /> </div> </template> <script> import SearchForm from '@/components/SearchForm' export default { components: { SearchForm }, data() { return { searchData: [ { label: '动态获取下拉组件', element: 'select', prop: 'issho2w', options: this.getMenu() }, { label: 'ID', element: 'input', prop: 'id' }, { label: '状态', element: 'select', prop: 'one', options: [ { label: '启用', value: '1' }, { label: '停用', value: '0' } ] }, { label: '第二种', element: 'select', prop: 'two', options: this.two() }, // 时间区间选择 // 注意的是时间区间选择返回的是一个数组,所以需要你根据返回的值拆分数据获取值 { label: '访问时间', element: 'date-picker', prop: 'cycle', initValue: [] }, // 时间选择 { label: '访问时间', element: 'date-picker-one', prop: 'time', initValue: [] } ] } }, methods: { // 这里是下拉组件是需要加载的 // 这里的话如果是异步,因为初始加载的时候没获取完成,所以传入搜索组件内就是空了! 方法的话是2种,一种就是我这种, // 另外一种的话就直接 自行加载完成后 使用 this.searchData[0].options= res 去改变searchData,就能触发子组件更新了 async getMenu() { var options = await modelList(this.listQuery) return options }, // 下拉组件可以直接返回的 two() { return [ { label: '启用', value: '1' }, { label: '停用', value: '0' } ] }, // 搜索,如果传入了时间区间,则需要拷贝一份数据进行处理,切记要拷贝,不能=,会各种bug,因为要删除 onSearch(searchData) { this.listQuery.page = 1 //跳转到第一页 const data = Object.assign({}, searchData) // 获取搜索的值 if (Array.isArray(data.cycle)) { data.startDate = data.cycle[0] data.endDate = data.cycle[1] delete data.cycle } else { this.listQuery.startDate = '' this.listQuery.endDate = '' } this.listQuery = Object.assign({}, this.listQuery, data) this.getList() }, /* // 如果没有传入时间区间,就直接合并初始页码进行搜索即可! onSearch (searchData) { this.listQuery.page = 1 this.listQuery = Object.assign({}, this.listQuery, searchData) this.getList() } */ } } </script> <style> </style>
3、代码
components --SearchForm ----FormItem.vue ----index.vue
index.vue
<template> <el-form ref="formRef" :model="formData" :inline="true"> <el-form-item v-for="(item, index) in formOptions" :key="index" :prop="item.prop" :label="item.label ? item.label + '' : ''" :rules="item.rules" > <form-item v-model="formData[item.prop]" :item="item" @onSearch="onSearch()" /> </el-form-item> <el-form-item> <el-button type="primary" size="small" icon="el-icon-search" @click="onSearch()">查询</el-button> <el-button v-if="btnItems.includes('reset')" size="small" icon="el-icon-refresh" @click="onReset()" >重置</el-button> <el-button v-if="btnItems.includes('export')" size="mini" type="primary" class="btn-export" @click="onExport" >导出</el-button> </el-form-item> </el-form> </template> <script> import FormItem from './FormItem.vue' export default { name: 'SearchForm', components: { FormItem }, props: { formOptions: { type: Array, default: () => [] }, // 提交按钮项,多个用逗号分隔(query, export, reset) btnItems: { type: String, default: "reset" } }, data() { return { formData: {} } }, computed: { widthSize() { const dataSize = this.formOptions.length if (dataSize < 4) { return 24 / (dataSize + 1) } else { return 6 } } }, created() { this.addInitValue() }, methods: { // 校验 onValidate(callback) { this.$refs.formRef.validate(valid => { if (valid) { callback() } }) }, // 搜索 onSearch() { this.onValidate(() => { this.$emit('onSearch', this.formData) }) }, // 导出 onExport() { this.onValidate(() => { this.$emit('onExport', this.formData) }) }, // 重置 onReset() { this.$refs.formRef.resetFields() this.addInitValue()// 重置后需要初始化数据 this.$emit('onSearch', this.formData) }, // 添加初始值 addInitValue() { const obj = {} this.formOptions.forEach(v => { if (v.initValue !== undefined) { obj[v.prop] = v.initValue // this.$set(this.formData) } }) this.formData = Object.assign({}, this.formData, obj) } } } </script> <style> </style>
FormItem.vue
<template> <div class="form-item"> <!-- 文本 --> <el-input v-if="item.element === 'input'" v-model.trim="currentVal" clearable v-bind="bindProps" size="small" @clear="clearInput()" @keyup.enter.native="handleFilter()" /> <el-input v-if="item.element === 'numberinput'" v-model.number="currentVal" clearable size="small" @keyup.enter.native="handleFilter()" /> <!-- 数字 --> <el-input-number v-if="item.element === 'number'" v-model="currentVal" v-bind="bindProps" clearable size="small" :controls-position="item['controls-position'] || 'left'" v-on="bindEvents" /> <!-- select --> <el-select v-if="item.element === 'select'" v-model="currentVal" v-bind="bindProps" clearable size="small" v-on="bindEvents" @change="handleFilter" > <el-option v-for="v in options" :key="v.value" :label="v.label" :value="v.value" /> </el-select> <!-- date-picker --> <el-date-picker v-if="item.element === 'date-picker'" v-model="currentVal" v-bind="bindProps" size="small" type="daterange" clearable :picker-options="pickerOptions" start-placeholder="开始日期" range-separator="至" end-placeholder="结束日期" value-format="yyyy-MM-dd" v-on="bindEvents" /> <!-- date-picker-one --> <el-date-picker v-if="item.element === 'date-picker-one'" v-model="currentVal" type="date" placeholder="选择日期" v-bind="bindProps" size="small" value-format="yyyy-MM-dd" v-on="bindEvents" /> </div> </template> <script> export default { name: 'FormItem', props: { value: {}, item: { type: Object, default: () => { } } }, data() { return { options: [], pickerOptions: { shortcuts: [ { text: '最近一天', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 1) picker.$emit('pick', [start, end]) } }, { text: '最近三天', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 3) picker.$emit('pick', [start, end]) } }, { text: '最近一周', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 7) picker.$emit('pick', [start, end]) } }, { text: '最近一月', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 30) picker.$emit('pick', [start, end]) } } ] } } }, created() { if (this.item.options) { this.option(this.item.options) } }, computed: { // 双向绑定数据值 currentVal: { get() { return this.value }, set(val) { this.$emit('input', val) } }, // 绑定属性 bindProps() { const objs = { ...this.item } // 默认填充placeholder if (!objs.placeholder) { const msg = objs.element === 'input' ? '请输入' : '请选择' objs.placeholder = msg + objs.label } // 移除冗余属性 delete objs.prop delete objs.initValue delete objs.rules delete objs.events if (objs.element === 'select') { delete objs.options } delete objs.element console.log(objs) return objs }, // 绑定方法 bindEvents() { return this.item.events || {} } }, methods: { // 选中即执行 handleFilter() { this.$emit('onSearch') }, // 清空亦执行搜索 clearInput() { this.$emit('onSearch') }, // 判断option是否是Promise对象,如果是的话,把Promise对象输出 option(obj) { var isPromise = !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function' if (isPromise) { obj.then(res => { console.log(res) this.options = res.data.list }) } else { this.options = obj } } } } </script> <style></style>