参考ui:DropDown 下拉筛选 | 我的资料管理-uv-ui 是全面兼容vue3+2、nvue、app、h5、小程序等多端的uni-app生态框架
样式示例:
封装公用文件代码 dropDownTemplete
<template>
<!-- 顶部下拉筛选区封装公用组件 -->
<view>
<uv-drop-down ref="dropDown" sign="dropDown_1" :defaultValue="defaultValue" @click="selectMenu">
<uv-drop-down-item v-for="(item,index) in uvDropDownItem" :name="item.name" type="2"
:label="dropItem(item.name,index).label" :value="dropItem(item.name,index).value">
</uv-drop-down-item>
<uv-drop-down-item name="more" type="1" label='更多' extra-icon='empty-search' :value="0">
</uv-drop-down-item>
</uv-drop-down>
<uv-drop-down-popup sign="dropDown_1" :click-overlay-on-close="true" :currentDropItem="currentDropItem"
@clickItem="clickItem"></uv-drop-down-popup>
<!-- 更多搜索 -->
<view class="popupPosition">
<uv-popup ref="popup" :safeAreaInsetTop="true">
<view class="content">
<view style="padding: 20rpx;">
<uv-form labelPosition="left" :model="filterSheetData" ref="form">
<uv-form-item v-for="(item,index) in formItem" :label="item.label" :prop="item.vModel"
labelWidth="120" borderBottom width="150rpx" @click="handleItemClick(item)">
<uv-input v-model="filterSheetData[item.vModel]" disabled disabledColor="#ffffff"
:placeholder="item.placeholder" border="none"></uv-input>
<uv-icon v-if="item.selectIcon" name="arrow-right"
style="float: right;margin-right: 20rpx;"></uv-icon>
</uv-form-item>
<uv-button type="primary" text="搜索" customStyle="margin-top: 10px"
@click="searchSheet"></uv-button>
<uv-button type="error" text="重置" customStyle="margin-top: 10px"
@click="resetSearchSheet"></uv-button>
</uv-form>
</view>
</view>
</uv-popup>
<uv-popup ref="calendarsPopup" mode="bottom">
<view class="calendarPopupStyle">
<view class="cancel" @click="calendarsCancel">
取消
</view>
<view class="confirm" @click="calendarsConfirm">
确定
</view>
</view>
<uv-calendars ref="calendars" insert mode="range" @confirm="(e)=>timeConfirm(e,calendarsType)"
@change="(e)=>timeConfirm(e,calendarsType)" />
</uv-popup>
<uv-picker v-if="pickerShow" ref="picker" :columns="pickerColumns" keyName="label"
@confirm="(e)=>pickerConfirm(e,pickerType)" @close="pickerClose"></uv-picker>
<uv-input v-if="pickerInputShow" placeholder="请输入筛选内容" border="surround" clearable v-model="pickerValue"
@change="pickerSearchChange" @clear="pickerSearchClear" :customStyle="pickerIptStyle"></uv-input>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
// 表示value等于这些值,就属于默认值
defaultValue: [0, 'all', '0'],
result: [],
activeName: '',
pickerType: "",
pickerShow: false,
pickerInputShow: false,
pickerIptStyle: {
position: 'fixed',
bottom: '220px',
transform: 'translate(-50%)',
zIndex: 997
},
pickerColumns: [
[{
label: '数据加载失败',
id: 0
}]
],
queryParams: {
json: {
conditions: [],
formId: '',
orderBys: [],
}
},
pickerValue: ''
}
},
props: {
// 下拉选项数据
uvDropDownItem: {
type: Array,
default: () => ([])
},
// 更多下拉选中表单数据
filterSheetData: {
type: Object,
default: () => ({})
},
filternetworkData: {
type: Object,
default: () => ({})
},
filterinitialData: {
type: Object,
default: () => ({})
},
// 表单项字段
formItem: {
type: Array,
default: () => ([])
},
// 更多筛选中下拉数据列表
olumnscData: {
type: Array,
default: () => ([])
},
},
computed: {
dropItem(name, index) {
return (name, index) => {
const result = {};
const find = this.result.find(item => item.name === name);
if (find) {
result.label = find.label;
result.value = find.value;
} else {
result.label = this.uvDropDownItem[index][name].label;
result.value = this.uvDropDownItem[index][name].value;
}
return result;
}
},
// 获取当前下拉筛选项
currentDropItem() {
let data = this.uvDropDownItem.find(item => item.name === this.activeName)
// console.log(data&&data.name);//拿到name字段
// console.log(data&&data[data.name]);//获取name字段中的数组
return data && data[data.name]
}
},
created() {},
methods: {
// 更多筛选中表单点击事件
handleItemClick(item) {
if (item.selectIcon) {
if (item.type === 'text') {
this.chooseSearchSelect(item.vModel);
} else if (item.type === 'time') {
this.chooseSearchTime(item.vModel);
}
}
},
// 选择内容(下拉选)
chooseSearchSelect(type) {
this.pickerType = type
this.pickerColumnsAssignment()
this.pickerShow = true
this.$nextTick(() => {
this.$refs.picker.open();
})
setTimeout(() => {
this.pickerIptStyle['left'] = window.innerWidth / 2 + 'px'
this.pickerInputShow = true
}, 300)
},
pickerColumnsAssignment() {
this.olumnscData.forEach(item => {
if (item.name == this.pickerType) {
this.$set(this.pickerColumns, 0, item.list)
}
})
},
// 快速过滤选择项
pickerSearchChange(e) {
if (e === '') {
this.pickerColumnsAssignment()
} else {
this.olumnscData.forEach(item => {
if (item.name == this.pickerType) {
this.$set(this.pickerColumns, 0, item.list.filter((item) => item.label.includes(e)))
}
})
}
},
// 快速过滤选择项清除
pickerSearchClear() {
this.pickerColumnsAssignment()
},
// 选择项确定
pickerConfirm(e, type) {
this.filternetworkData[type] = e.value[0]
this.filterSheetData[type] = e.value[0].label
},
// 选择项取消
pickerClose() {
this.pickerShow = false
this.pickerInputShow = false
},
// 选择时间
chooseSearchTime(type) {
this.calendarsType = type
this.$refs.calendarsPopup.open();
},
// 选择时间取消
calendarsCancel() {
this.filternetworkData[this.calendarsType] = ""
this.filterSheetData[this.calendarsType] = ""
this.$refs.calendarsPopup.close();
},
// 选择时间确定
calendarsConfirm() {
this.$refs.calendarsPopup.close();
},
timeConfirm(e, type) {
this.filternetworkData[type] = e.range
this.filterSheetData[type] = e.range.before + ' / ' + e.range.after
},
//更多--搜索
searchSheet() {
this.queryParams.json.conditions = []
this.formItem.forEach(item => {
// 判断查询表单项是否有值
if (this.filternetworkData[item.vModel]&&item.type=='text') {
// 如果value有值说明是对象格式 将value值传递
if (this.filternetworkData[item.vModel].value) {
this.queryParams.json.conditions.push({
field: item.vModel,
operation: "like",
value: this.filternetworkData[item.vModel].value
})
// 如果只是字段有值 说明是文本框
} else {
this.queryParams.json.conditions.push({
field: item.vModel,
operation: "like",
value: this.filternetworkData[item.vModel]
})
}
}
if (this.filternetworkData[item.vModel]&&item.type=='time') {
this.queryParams.json.conditions.push({
field: item.vModel,
operation: "<>",
value: this.filternetworkData[item.vModel].before,
value2: this.filternetworkData[item.vModel].after
})
}
})
this.$refs.popup.close()
// 将查询条件传递给父组件
this.$emit('searchSheet', this.queryParams.json)
},
resetSearchSheet() {
this.$emit('resetSearchSheet')
this.queryParams.json.conditions = []
this.$refs.popup.close()
},
/**
* 点击每个筛选项回调
* @param {Object} e { name, active, type } = e
*/
selectMenu(e) {
const {
name,
active,
type
} = e;
this.activeName = name;
// type 等于1 的需要特殊处理:type不等于1可以忽略
if (type == 1) {
this.$refs.popup.open('top');
} else {
// 找到 name 属性等于 this.activeName 的对象
const dropDownItem = this.uvDropDownItem.find(item => item.name === this.activeName);
if (dropDownItem) {
const find = this.result.find(item => item.name == this.activeName);
if (find) {
const findIndex = dropDownItem.child.findIndex(item => item.label == find.label && item
.value == find.value);
dropDownItem.activeIndex = findIndex;
} else {
dropDownItem.activeIndex = 0;
}
}
}
},
/**
* 点击菜单回调处理
* @param {Object} item 选中项 { label,value } = e
*/
clickItem(e) {
// 下面有重新赋值,所以用let
let {
label,
value
} = e;
const findIndex = this.result.findIndex(item => item.name == this.activeName);
if (this.defaultValue.indexOf(value) > -1 && this[this.activeName].label) {
label = this[this.activeName].label;
}
// 已经存在筛选项
if (findIndex > -1) {
this.$set(this.result, findIndex, {
name: this.activeName,
label,
value
})
} else {
this.result.push({
name: this.activeName,
label,
value
});
}
this.result = this.result.filter(item => this.defaultValue.indexOf(item.value) == -1);
this.result.forEach(item => {
if (item.name) {
if (item.label == '全部') {
if (this.queryParams.json.conditions.length) {
this.queryParams.json.conditions.forEach((itens,indexs)=>{
if(itens.field === item.name){
this.queryParams.json.conditions.splice(indexs,1)
}
})
}
} else {
// 添加筛选参数
if (this.queryParams.json.conditions.length) {
this.queryParams.json.conditions.forEach((itens,indexs)=>{
if(itens.field === item.name){
this.queryParams.json.conditions.splice(indexs,1)
}
})
this.queryParams.json.conditions.push({
field: item.name,
operation: "=",
value: item.value
})
} else {
this.queryParams.json.conditions.push({
field: item.name,
operation: "=",
value: item.value
})
}
}
}
})
// 将查询条件传递给父组件
this.$emit('searchSheet', this.queryParams.json)
},
}
}
</script>
<style lang="scss" scoped>
// 下拉选项滚动区域
::v-deep .uv-dp__container {
height: 400rpx !important;
overflow-y: auto;
}
uni-view[data-v-4cc3c370] {
top: 0 !important;
}
.calendarPopupStyle {
display: flex;
justify-content: space-between;
border-bottom: 1rpx solid #ccc;
>view {
font-size: 34rpx;
color: #909399;
padding: 20rpx 20rpx;
}
}
</style>
父组件调用:
<view class="header-fixed">
<dropDownTemplete :uvDropDownItem="uvDropDownItem" :filterSheetData="filterSheetData" :filternetworkData="filternetworkData"
:filterinitialData="filterinitialData" :formItem="formItem" :olumnscData="olumnscData" @searchSheet="searchSheet" @resetSearchSheet="resetSearchSheet"></dropDownTemplete>
</view>
data数据:
// 下拉选项数据
uvDropDownItem: [{
name: 'brand',
brand: {
label: '品牌',
value: 'all',
activeIndex: 0,
color: '#333',
activeColor: '#2878ff',
child: [{
label: '全部',
value: 'allto'
}]
},
},
{
name: 'categoryId',
categoryId: {
label: '品类',
value: 'all',
activeIndex: 0,
color: '#333',
activeColor: '#2878ff',
child: [{
label: '全部',
value: 'allto'
}]
}
}
],
// 更多下拉选项数据
formItem:[
{
label:'品类',
vModel:'categoryId',
type:'text',
placeholder:'请选择品类',
selectIcon:true
},
{
label:'品牌',
vModel:'brand',
type:'text',
placeholder:'请选择品牌',
selectIcon:true
},
{
label:'更新时间',
vModel:'updateTime',
type:'time',
placeholder:'请选择更新时间',
selectIcon:true
},
{
label:'创建时间',
vModel:'createTime',
type:'time',
placeholder:'请选择创建时间',
selectIcon:true
}
],
filterSheetData: {
categoryId: "",
brand: "",
updateTime: "",
createTime: ""
},
filternetworkData: {
categoryId: "",
brand: "",
updateTime: "",
createTime: ""
},
filterinitialData: {
categoryId: "",
brand: "",
updateTime: "",
createTime: ""
},
olumnscData:[
{
name:'categoryId',
list:[
{label:'1',vaule:'fff'},
{label:'2',vaule:'dfvdgf'}
],
},
{
name:'brand',
list:[
{label:'里奈',vaule:'里奈'},
{label:'舞曲',vaule:'舞曲'}
],
}
]
搜索和清除事件:
// 更多-搜索
searchSheet(data){
console.log(data);
//这里可进行搜索操作
},
// 更多-清除
resetSearchSheet(){
// 清空数据
this.filterSheetData = this.filterinitialData
this.filternetworkData = {
categoryId: {label:'',value:''},
brand: {label:'',value:''},
updateTime: "",
createTime: ""
}
},
最终样式图示例: