目录
1.搜索框组件
封装
<template>
<div class="search-filter-wrapper">
<div @keyup.enter="searchConfirm" class="display-inline-block input-search-wrapper">
<el-input
class="search-input"
:style="`width:${searchWidth}`"
:placeholder="placeholder"
v-model="searchModel"
:maxlength="40"
clearable
>
<i slot="prefix" class="el-input__icon el-icon-search fontSize15" />
</el-input>
<el-button class="search-btn primary-btn" type="primary" @click="searchConfirm">
<span class="el-icon-search fontSize15"></span>
<span>{
{ label }}</span>
</el-button>
</div>
</div>
</template>
<script>
export default {
name: 'search-filter',
props: {
// 宽度
searchWidth: {
type: String,
default: '500px'
},
placeholder: {
type: String,
default: '请输入你要搜索的内容'
},
label: {
type: String,
default: '搜索'
}
},
data() {
return {
//input输入框的值
searchModel: '',
// 用来做简单防抖函数所用
timer: null
};
},
methods: {
// 回车或者点击搜索触发
searchConfirm() {
// 简单弄个防抖函数
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.searchModel = this.searchModel.replace(/(^\s+)|(\s+$)/g, '');
this.$emit('change', this.searchModel);
}, 500);
}
}
};
</script>
<style lang="scss" scoped>
.search-filter-wrapper {
display: inline-block;
.display-inline-block {
display: inline-block;
.search-input {
height: 36px;
vertical-align: middle;
}
}
.search-btn {
position: relative;
vertical-align: middle;
}
}
</style>
使用
<template>
<search-filter
ref="searchFilter"
placeholder="客户姓名、编号"
@change="searchValueChange"
/>
</template>
import searchFilter from '@/components/common/searchFilter';
export default{
data(){
return {
// 搜索的值
serachStr:''
}
}
components: {searchFilter},
methods:{
// 获取搜索变化值
searchValueChange(value){
this.serachStr = value
// 发起请求获取数据
this.getData();
}
}
}
2.筛选组件
用数据来驱动,用数组来快速搭建筛选组件,让你摆脱烦恼~
暂时只封装了 输入框、文本域、下拉框(单选|多选)、带搜索的输入框、单选、级联选择
后续慢慢完善
封装
<template>
<div class="tableFilter-layout">
<!-- 可能有众多条件,弄成个数据 -->
<template v-for="(item, index) in editMsgObj">
<span class="list-filter-item" :key="index">
<!-- 各个筛选框前的文字描述 -->
<span class="list-filter-item-key" v-if="item.text">{
{ item.text || '' }}:</span>
<!-- 筛选框 用来判断是哪类筛选框 -->
<span class="list-filter-item-input-wrapper">
<!-- 输入框 || 文本域 -->
<template v-if="item.type === 'input' || item.type === 'textarea'">
<el-input
v-model="item.model"
:type="item.type === 'textarea' ? 'textarea' : 'text'"
:name="item.elemName"
:maxlength="item.maxlength || 50"
:placeholder="item.placeholder || ''"
:rows="4"
:disabled="!!item.disabled"
@change="changeItemValue(item)"
/>
</template>
<!-- 下拉框单选 || 下拉框多选-->
<template v-else-if="item.type === 'select' || item.type === 'multipleSelect'">
<el-select
v-model="item.model"
popper-class="default-select-dropdown"
:name="item.elemName"
:disabled="!!item.disabled"
:placeholder="item.placeholder || '- -'"
:clearable="!item.cleardisable || item.type === 'multipleSelect'"
:multiple="item.type === 'multipleSelect'"
:filterable="!!item.filterable"
:collapse-tags="item.type === 'multipleSelect'"
@change="changeItemValue(item)"
>
<template v-for="type in item.values">
<el-option
:label="type.itemName"
:value="type.itemKey"
:key="type.itemKey"
></el-option>
</template>
</el-select>
</template>
<!-- 带搜索的输入框 -->
<template v-else-if="item.type === 'search'">
<span @keyup.enter="searchFunc" class="display-inline-block input-search-wrapper">
<el-input
class="search-input"
:placeholder="item.placeholder"
v-model="item.model"
:maxlength="item.maxlength || 50"
:clearable="!item.cleardisable"
>
<i slot="prefix" class="el-input__icon el-icon-search fontSize15"></i>
</el-input>
<el-button class="search-btn primary-btn" type="primary" @click="searchFunc">
<span class="el-icon-search fontSize15"></span>
<span>搜索</span>
</el-button>
</span>
</template>
<!-- 单选-->
<template v-else-if="item.type === 'radio'">
<el-radio-group v-model="item.model" :name="item.name" @change="changeItemValue(item)">
<template v-for="(type, idx) in item.values">
<el-radio :label="type.itemKey" :key="idx">
{
{ type.itemName }}
</el-radio>
</template>
</el-radio-group>
</template>
<!-- 级联选择 -->
<template v-if="item.type === 'cascader'">
<el-cascader
popper-class="default-select-dropdown"
v-model="item.model"
:options="item.values"
:clearable="true"
:collapse-tags="true"
:show-all-levels="false"
:props="{
value: 'itemKey',
label: 'itemName',
children: 'children',
multiple: !item.checkStrictly,
checkStrictly: !!item.checkStrictly
}"
placeholder="请选择内容"
@change="changeItemValue(item)"
></el-cascader>
</template>
</span>
</span>
</template>
<!-- 如果需要有输入框 -->
<el-button
v-if="searchBtn"
class="search-btn primary-btn"
type="primary"
@click="searchBtnFunc"
>
<span class="el-icon-search fontSize15"></span>
<span>搜索</span>
</el-button>
</div>
</template>
<script>
export default {
name: 'tableFilter',
components: {},
filters: {},
props: {
// 编辑内容
editObj: {
type: [Object, Array],
default: function () {
return {};
}
},
// 是否需要搜索确认框
searchBtn: Boolean
},
data() {
return {
// 是否是数组 数组返回整个对象,对象返回key-value
ifArray: false,
// 编辑内容
editMsgObj: {},
// 搜索
searchModel: ''
};
},
computed: {},
watch: {
// 实时更新
editObj: {
handler(to, from) {
this.editMsgObj = this.dealAdvanceList(this.deepCopy(this.editObj));
},
deep: true
}
},
mounted() {
this.editMsgObj = this.dealAdvanceList(this.deepCopy(this.editObj));
},
methods: {
/**
* 监听方法
*/
// 初始化 用来清空值 比如 this.$refs.listFitler.initFunc() 这样调用;
initFunc() {
this.editMsgObj = this.dealAdvanceList(this.deepCopy(this.editObj));
},
// 处理值
dealAdvanceList(data) {
data = data || {};
let resData = {};
// 判断是否是数组还是对象
if (data instanceof Array) {
this.ifArray = true;
data.forEach((item, index) => {
resData[item.name] = item;
});
} else {
this.ifArray = false;
resData = data;
}
return resData;
},
// 选项触发
changeItemValue() {
if (this.searchBtn) return;
this.changeVal(this.editMsgObj);
},
// 改变editObj某一项的值 例如this.$refs.editItem.changeEditModelVal('isRepay', 'hidden', true);
changeEditModelVal(key, attr, val) {
if (!this.editMsgObj[key]) {
return;
}
this.editMsgObj[key][attr] = val;
},
// 值改变,数据拼接
changeVal(obj) {
let newObj = {};
let newArr = [];
for (let key in obj) {
if (Array.isArray(obj[key].model) && obj[key].model.length > 0) {
console.log(88);
// 返回的数据是数组类型 例如 多选 级联选择器
newObj[key] = obj[key].model;
let idx = newArr.length;
newArr.push(this.deepCopy(obj[key]));
obj[key].model.forEach((itemValue, itemIdx) => {
newArr[idx].values.push({
itemKey: itemValue
});
});
delete newArr[idx].model;
} else if (obj[key].model || obj[key].model === 0) {
// 返回的数据是字符串类型 例如单选 文本输入框
console.log(666);
newObj[key] = obj[key].model;
let idx = newArr.length;
newArr.push(this.deepCopy(obj[key]));
newArr[idx].values = [{ itemKey: obj[key].model }];
delete newArr[idx].model;
} else if (obj[key].type === 'search' && obj[key].model) {
newObj[key] = obj[key].model;
let idx = newArr.length;
newArr.push(this.util.deepCopy(obj[key]));
newArr[idx].value = obj[key].model;
}
}
let result = this.ifArray ? newArr : newObj;
this.$emit('editMsgObjChange', result);
},
// 搜索
searchFunc() {
this.changeVal(this.editMsgObj);
},
// 搜索按钮促发
searchBtnFunc() {
this.changeVal(this.editMsgObj);
},
// 深拷贝
deepCopy(o) {
// 数组
if (o instanceof Array) {
return o.map((item) => {
return this.deepCopy(item);
});
} else if (o instanceof Function) {
return o;
} else if (o instanceof Object) {
let temp = {};
Object.keys(o).map((item) => {
temp[item] = this.deepCopy(o[item]);
});
return temp;
} else {
return o;
}
}
}
};
</script>
<style lang="scss" scoped>
.tableFilter-layout {
.list-filter-item {
display: inline-block;
margin-bottom: 10px;
margin-right: 10px;
.el-input {
width: 185px;
}
}
}
</style>
使用
<!-- //?模块说明 => 模块 -->
<template>
<div class="About-layout">
<!--
editObj : 筛选条件数组
editMsgObjChange: 选项触发后
-->
<table-filter
ref="tableFitler"
:editObj="tableFilterData"
@editMsgObjChange="changeFilterObj"
:searchBtn="true"
></table-filter>
</div>
</template>
<script>
import tableFilter from './components/tableFilter';
export default {
name: 'About',
components: { searchFilter, tableFilter },
filters: {},
props: {},
data() {
return {
searchStr: '',
tableFilterData: {
// 活动类型
activeType: {
name: 'activeType',
// 规定类型 => 下拉框多选
type: 'multipleSelect',
// 显示筛选框前面的文字
text: '流转类型',
// 选中的数据,因为是多选,所以是数组
model: [],
elemName: 'list-activeType',
// 供选择的数据,可以通过接口获得,也可以写死
values: [
{ itemKey: 0, itemName: '吃饭' },
{ itemKey: 1, itemName: '睡觉' }
],
// 默认提示文字
placeholder: '全部',
// 是否可删除
clearable: true
},
// 是否成交
isHasBuy: {
name: 'isHasBuy',
// 规定类型 => 下拉框单选
type: 'select',
text: '是否成交',
// 选中的数据,因为是单选,所以是字符串
model: '',
elemName: 'list-isHasBuy',
// 供选择的数据,可以通过接口获得,也可以写死
values: [
{ itemKey: 0, itemName: '成交' },
{ itemKey: 1, itemName: '未成交' }
],
placeholder: '全部',
clearable: true
},
// 搜索框
fuzzySearch: {
name: 'fuzzySearch',
// 规定类型 => 有搜索的输入框,一般一个页面只使用一个
type: 'search',
// 输入的数据,
text: '',
placeholder: '请输入内容',
model: '',
elemName: 'list-fuzzySearch'
},
// 性别
sex: {
name: 'sex',
// 规定类型 => 单选
type: 'radio',
text: '性别',
// 选择的数据,
model: '',
maxlength: 20,
elemName: 'list-sex',
values: [
{ itemKey: 0, itemName: '男' },
{ itemKey: 1, itemName: '女' }
]
},
// 地区
areas: {
name: 'areas',
type: 'cascader',
text: '地区',
model: [],
value: '',
disabled: false,
values: [
{
itemKey: 110000,
itemName: '北京',
children: [
{
itemKey: 110100,
itemName: '北京市'
}
]
},
{
itemKey: 410000,
itemName: '河南省',
children: [
{
itemKey: 410100,
itemName: '郑州市'
},
{
itemKey: 410200,
itemName: '开封市'
}
]
}
],
elemName: 'list-areas',
span: 8,
cleardisable: true,
filterable: true,
validateObj: {
errorTip: '',
ifRequiredFill: false
}
}
}
};
},
computed: {},
watch: {},
mounted() {
let obj = [];
// console.log({}.toString.call(obj));
// console.log([].toString.call(obj));
},
methods: {
/**
* 监听方法
*/
// 筛选条件变动
changeFilterObj(obj) {
console.log(obj);
}
/**
* 请求数据
*/
}
};
</script>
<style lang="scss" scoped>
//.About-layout{}
</style>
后续会慢慢更新其他的筛选,比如常用的还有时间选择框、敬请期待!