1.父页面调用写法:
<searchFormC
:formOptions="formOptions"
:btnItems="btnItems"
></searchFormC>
// 引入
import searchFormC from "../common/form/searchForm.vue";
// data里面定义
formOptions: [
{
label: "",
prop: "title",
element: "el-input",
placeholder:'请输入关键字进行查询',
"prefix-icon": "el-icon-search",
clearable: true,
},
],
// 也可以将其定义为计算属性,加入按钮显示不显示的判断
btnItemsNoLink: [
{
id: "search",
size: "mini",
type: "primary",
disabled: false,
text: "查询",
events: {
click: (val, e) => {
// 本页面方法
this.onSearch(val);
},
},
},
{
id: "batchAdd",
size: "mini",
type: "primary",
disabled: true,
text: "批量添加",
events: {
click: () => {
this.onBatchAdd();
},
},
},
],
2.搜索栏公共组件
<!--搜索栏公共组件-->
<template>
<div class="search-form-box">
<el-form class="form-box" ref="formRef" :model="formData" :inline="true">
<el-form-item
v-for="(item, index) in formOptions"
:key="newKeys[index]"
:prop="item.prop"
:label="item.label ? item.label + ': ' : ''"
:rules="item.rules"
>
<formItem v-model="formData[item.prop]" :itemOptions="item"></formItem>
</el-form-item>
</el-form>
<!-- 提交按钮 -->
<div class="btn-box">
<template v-for="(item, index) in btnItems">
<buttonItem :key="index" :itemOptions="item" :formData="formData"></buttonItem>
</template>
</div>
</div>
</template>
<script>
import formItem from "./formItem";
import buttonItem from "./buttonItem.vue";
import { createUniqueString } from "../../../utils/tools";
export default {
props: {
/**
* 表单配置
* 示例:
* [{
* label: '用户名', // label文字
* prop: 'username', // 字段名
* element: 'el-input', // 指定elementui组件
* initValue: '阿黄', // 字段初始值
* placeholder: '请输入用户名', // elementui组件属性
* rules: [{ required: true, message: '必填项', trigger: 'blur' }], // elementui组件属性
* events: { // elementui组件方法
* input (val) {
* console.log(val)
* },
* ...... // 可添加任意elementui组件支持的方法
* }
* ...... // 可添加任意elementui组件支持的属性
* }]
*/
formOptions: {
type: Array,
required: true,
default() {
return [];
},
},
/**
* 提交按钮项,按钮配置
* 示例:
* [
{
size:"mini",
type:"primary",
disabled:false,
text:"查询",
events:{
click(val,e){
console.log(val,e)
}
...... // 可添加任意elementui组件支持的方法
}
}
...... // 可添加任意elementui组件支持的属性
]
*/
btnItems: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
formData: {},
};
},
components: { formItem ,buttonItem},
computed: {
newKeys() {
return this.formOptions.map((v) => {
return createUniqueString();
});
},
},
created() {
this.addInitValue();
},
mounted() {},
methods: {
// 校验
onValidate(callback) {
this.$refs.formRef.validate((valid) => {
if (valid) {
// console.log("提交成功");
// console.log(this.formData);
callback();
}
});
},
// 添加初始值
addInitValue() {
const obj = {};
this.formOptions.forEach((v) => {
if (v.initValue !== undefined) {
obj[v.prop] = v.initValue;
}
});
this.formData = obj;
},
},
};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>
.search-form-box {
margin-top: 5px;
display: flex;
}
.form-box {
margin-left: 5px;
}
.btn-box {
padding-top: 5px;
display: flex;
}
button {
height: 28px;
}
.el-form-item {
margin-bottom: 5px;
}
</style>
3.按钮组件写法
使用v-on完成多个事件的绑定,解决回调传参问题。参考bindBtnEvents方法
<template>
<div class="btn-item">
<el-button plain v-bind="bindBtnProps" v-on="bindBtnEvents">
{{ itemOptions.text }}</el-button
>
</div>
</template>
<script>
export default {
inheritAttrs: false,
props: {
itemOptions: {
type: Object,
default() {
return {};
},
},
formData: {
type: Object,
default() {
return {};
},
},
},
data() {
return {};
},
components: {},
computed: {
bindBtnProps() {
let obj = { ...this.itemOptions };
// 移除冗余属性
delete obj.text;
delete obj.events;
return obj;
},
// 绑定方法
bindBtnEvents() {
let events = this.itemOptions.events;
if (!events) {
return {};
}
let result = Object.keys(events).reduce((cur,next)=>{
cur[next] = events[next].bind(this,this.formData)
return cur
},{})
return result;
},
},
mounted() {},
methods: {},
};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>
.btn-item{
margin-left: 5px;
}
</style>
4.formItem 组件写法
<template>
<div class="form-item">
<el-input
v-if="isInput"
v-model="currentVal"
v-bind="bindProps"
v-on="bindEvents"
size="mini"
></el-input>
<el-input-number
v-if="isInputNumber"
v-model="currentVal"
v-bind="bindProps"
v-on="bindEvents"
:controls-position="itemOptions['controls-position'] || 'right'"
size="mini"
></el-input-number>
<el-select
v-if="isSelect"
v-model="currentVal"
v-bind="bindProps"
v-on="bindEvents"
size="mini"
clearable
>
<el-option
v-for="item in itemOptions.options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
<!-- datetimerange/daterange -->
<el-date-picker
v-if="isDatePickerDateRange"
v-model="currentVal"
v-bind="bindProps"
v-on="bindEvents"
:type="itemOptions.type || 'datetimerange'"
size="mini"
clearable
:picker-options="pickerOptionsRange"
start-placeholder="开始日期"
range-separator="至"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']"
value-format="yyyy-MM-dd HH:mm:ss"
></el-date-picker>
<!-- monthrange -->
<el-date-picker
v-if="isDatePickerMonthRange"
v-model="currentVal"
v-bind="bindProps"
v-on="bindEvents"
type="monthrange"
size="mini"
clearable
:picker-options="pickerOptionsRangeMonth"
start-placeholder="开始日期"
range-separator="至"
end-placeholder="结束日期"
value-format="yyyy-MM"
></el-date-picker>
<!-- others -->
<el-date-picker
v-if="isDatePickerOthers"
v-model="currentVal"
v-bind="bindProps"
v-on="bindEvents"
:type="itemOptions.type"
size="mini"
clearable
placeholder="请选择日期"
></el-date-picker>
<el-cascader
v-if="isCascader"
v-model="currentVal"
v-bind="bindProps"
v-on="bindEvents"
size="mini"
clearable
></el-cascader>
</div>
</template>
<script>
import {pickerOptionsRange,pickerOptionsRangeMonth} from "@/utils/tools";
export default {
inheritAttrs: false,
props: {
value: {},
itemOptions: {
type: Object,
default() {
return {};
},
},
},
data() {
return {
pickerOptionsRange: pickerOptionsRange,
pickerOptionsRangeMonth: pickerOptionsRangeMonth,
};
},
components: {},
computed: {
currentVal: {
get() {
return this.value;
},
set(val) {
this.$emit("input", val);
},
},
bindProps() {
let obj = { ...this.itemOptions };
// 移除冗余属性
delete obj.label;
delete obj.prop;
delete obj.element;
delete obj.initValue;
delete obj.rules;
delete obj.events;
if (obj.element === "el-select") {
delete obj.options;
}
return obj;
},
// 绑定方法
bindEvents() {
return this.itemOptions.events || {};
},
// el-input
isInput() {
return this.itemOptions.element === "el-input";
},
// el-input-number
isInputNumber() {
return this.itemOptions.element === "el-input-number";
},
// el-select
isSelect() {
return this.itemOptions.element === "el-select";
},
// el-date-picker (type: datetimerange/daterange)
isDatePickerDateRange() {
const isDatePicker = this.itemOptions.element === "el-date-picker";
const isDateRange =
!this.itemOptions.type ||
this.itemOptions.type === "datetimerange" ||
this.itemOptions.type === "daterange";
return isDatePicker && isDateRange;
},
// el-date-picker (type: monthrange)
isDatePickerMonthRange() {
const isDatePicker = this.itemOptions.element === "el-date-picker";
const isMonthRange = this.itemOptions.type === "monthrange";
return isDatePicker && isMonthRange;
},
// el-date-picker (type: other)
isDatePickerOthers() {
const isDatePicker = this.itemOptions.element === "el-date-picker";
return (
isDatePicker &&
!this.isDatePickerDateRange &&
!this.isDatePickerMonthRange
);
},
// el-cascader
isCascader() {
return this.itemOptions.element === "el-cascader";
},
},
mounted() {},
methods: {},
};
</script>
5.tool.js
/**
* 创建唯一的字符串
* @return {string} ojgdvbvaua40
*/
export function createUniqueString() {
const timestamp = +new Date() + ''
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}
// elementui日期时间范围 快捷选项
export const pickerOptionsRange = {
shortcuts: [{
text: '今天',
onClick(picker) {
const end = new Date()
const start = new Date(new Date().toDateString())
start.setTime(start.getTime())
picker.$emit('pick', [start, end])
}
}, {
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(end.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])
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit('pick', [start, end])
}
}]
}
// elementui月份范围 快捷选项
export const pickerOptionsRangeMonth = {
shortcuts: [{
text: '今年至今',
onClick(picker) {
const end = new Date()
const start = new Date(new Date().getFullYear(), 0)
picker.$emit('pick', [start, end])
}
},
{
text: '最近半年',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 6)
picker.$emit('pick', [start, end])
}
},
{
text: '最近一年',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 12)
picker.$emit('pick', [start, end])
}
}
]
}
网友评论