在开发过程中,经常会遇到下拉框,有些时候内容过多,找起来也不方便,给他增加一个输入框,相当于用户输入某些信息,然后再下拉,符合输入内容的数据将会被展示出来,大大方便了用户操作体验。
话不多说,让我们开始吧!
1.先简单了解一下弹框,picker,当mode = selector,即可,具体可以看微信小程序官方文档,https://developers.weixin.qq.com/miniprogram/dev/component/picker.html
range 相当于整个下拉数组,range-key 展示的值,value 展示的值的索引,bindchange方法改变下拉选项时触发。
wxml:
<view class="origin_picker">
<input type="text" value="{{merchant_name?merchant_name:''}}" placeholder="请选择商户" bindinput="handlerInput" style="width:300rpx;height: 100%;" />
</view>
<picker class="origin_select" bindchange="bindPickerBuyersName" range-key="merchant_name" range="{{Merchlist}}">
<image class="origin_img" src="xxx.png" alt="此处是下拉箭头"></image>
</picker>
wxss:
.origin_select {
width: 100rpx;
height: 60rpx;
position: relative;
font-size: 32rpx;
font-family: Source Han Sans CN;
font-weight: 400;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-left: 80rpx;
}
.origin_picker {
font-size: 32rpx;
font-family: Source Han Sans CN;
font-weight: 400;
line-height: 58rpx;
color: #999999;
opacity: 1;
height: 64rpx;
width: 270rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-left: 20rpx;
}
.origin_img {
width: 30rpx;
height: 30rpx;
position: absolute;
right: 0rpx;
top: 17rpx;
}
js:
const {
wxRequest
} = require('../../utils/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
merchant_name: '',
goods_name: '请选择',
Merchlist: [], // 展示的数据数组
Merchlist1: [], // 后台返回的数据数组
list: []
},
getMerchList() {
let data = ''
wxRequest('xxxxxx', data, 'POST', 'loading').then(res => {
this.setData({
Merchlist: res.data,
Merchlist1: res.data,
})
})
},
// 输入商户姓名
handlerInput(e){
let val = e.detail.value; // 用户输入的内容
const {Merchlist} =this.data;
if(val){
// 如果用户输入内容了,将原始数组进行过滤,过滤出符合用户输入的数组
let a = Merchlist.filter(item => item.merchant_name.indexOf(val) != -1)
this.setData({Merchlist:a})
}else{
// 用户没用输入或者清空了,则展示的数组为后台返回数组
this.setData({Merchlist:this.data.Merchlist1})
}
},
// 下拉弹框
bindPickerBuyersName(e) {
let i = e.detail.value; // 下拉选中的值的索引
let name = this.data.Merchlist[i].merchant_name; //展示数组的索引中的需要展示的内容的字段
let id = this.data.Merchlist[i].id; // 这是该字段实际要传给后端的id
// 下拉后需要将返回数据赋值给展示数据,否则下一次弹出下拉框不会展示全部数据
this.setData({
merchant_name: name,
merch_id: id,
goods_name: '请选择',
Merchlist:this.data.Merchlist1
})
},
onLoad: function (options) {
this.getMerchList();
},
})
就这样完成了
可以封装一下,以便后续使用。
可以再稍微增加点难度,不是直接下拉选择, 是通过市场id,请求数据,然后拿到摊位号进行选择,如图所示
梳理下需求:
1.从详情页进入,展示该页信息,如果有可以修改,没有就展示空也可以修改,然后根据市场id,获取下面摊位数据可供选择,同时也可以手动输入摊位信息进行筛选,提高用户体验。
父组件wxml ,css就不写了
// 父组件
<view class="search">
<span>市场编号:</span>
<input class="input" placeholder="请输入市场编号" bindinput="handlerInput" bindconfirm="handlerMarketNumber" value="{{market_id}}"></input>
</view>
<view class="search">
<span><text decode="{{true}}" space="{{true}}"> </text>摊位号:</span>
<view class="input input1">
// 子组件,封装好的输入下拉弹窗
<pickerinput list="{{list}}" _width="448rpx" _height="60rpx" bind:action="change" stall="{{stall_no}}" actualvalue="stall_no" showvalue="stall_no"></pickerinput>
</view>
</view>
父组件js
简单说明一下:
因为后台返的数据是分页的,我们需要市场下全部的摊位数组,所以前台这边处理下,
后台不忙的话,他们处理亦可。
首先获取市场id,第一次调getStall接口,赋值总共的页数last_page和第一页的数据list,
然后给一定延迟,获取到赋值完的last_page,再次进行循环ajax请求,并且每次current_page + 1,最后获取到所有数据的list。
var util = require("../../utils/util.js")
import {
wxRequest
} from "../../utils/util.js"
Page({
/**
* 页面的初始数据
*/
data: {
terminal_code: '',
scale_code: '',
market_id: '',
stall_no: '',
list:[],
current_page:1,
last_page:1,
},
// 获取市场id和摊位信息
getSearch(){
const {terminal_code} = this.data
let param ={
terminal_code,
}
wxRequest("xxxxx", param, "POST", 'loading').then(res => {
if(res.data.status ==1){
this.setData({
stall_no:res.data.data.stall_no,
market_id:res.data.data.market_id
})
}
this.setTimeGetInfo();
})
},
// 输入框输入时触发
handlerInput(e){
this.setData({
market_id:e.detail.value,
current_page:1,
list:[],
last_page:1,
});
this.setTimeGetInfo();
},
// 输入框确定时候触发
handlerMarketNumber(e) {
this.setData({ market_id: e.detail.value });
this.setTimeGetInfo();
},
// 后台返的数据进行一个处理优化,后台返的是分页数据,我这边需要全部下拉弹窗的数组信息,后端较忙,自己处理了,不忙的情况下,可以让后台直接返全部数据
setTimeGetInfo(){
this.getStall(this.data.current_page);
setTimeout(()=>{
for(var i = 0;i<=this.data.last_page; i++ ){
if(this.data.current_page <= this.data.last_page){
this.setData({
current_page: this.data.current_page + 1,
})
this.getStall(this.data.current_page);
// console.log(111,this.data.current_page,this.data.last_page)
}else{
return false
}
}
},500)
},
// ajax请求数据
getStall(page) {
const {market_id,current_page } = this.data;
let param ={market_id,page}
wxRequest("xxxx", param, "POST", 'loading').then(res => {
if (res.data) {
let a = this.data.list;
let b = [...a,...res.data.data];
this.setData({
list: b,
last_page:res.data.last_page,
})
} else {
// wx.showToast({
// title: res.data.msg,
// duration: 2000,
// icon: "none"
// })
}
})
},
onLoad: function (options) {
this.setData({ scale_code: options.scale_code, terminal_code: options.terminal_code })
this.getSearch()
},
})
子组件wxml,
<view style="width:{{_width}};height:{{_height}};" class="uni-picker-input">
<input value="{{picker_value}}" class="picker-item-input" bindinput="bindkeyinput" value="{{stall}}" placeholder="请输入摊位号" placeholder-style="font-size:32rpx"/>
<picker style="width:30%;height:100%;" bindchange="bindchange" value="{{list2[index][actualvalue]}}" range-key="{{showvalue}}" range="{{list2}}">
<view class='uni-picker-icon'>
<image src="../../img/down.png" class='img' />
</view>
</picker>
</view>
子组件的wxss
.uni-picker-input {
display: flex;
flex-direction: space-between;
border-radius: 14rpx;
/* border: 1rpx solid rgba(219,219,219,1); */
/* background: rgba(249,249,249,1); */
}
.picker-item-input {
/* margin-left: 10rpx; */
width: 80%;
height: 100%;
line-height: 60rpx;
/* font-size: 24rpx; */
/* padding-left: 10rpx; */
}
.uni-picker-icon {
width: 100%;
height: 100%;
/* background: red; */
display: flex;
align-items: center;
justify-content: flex-end;
}
.img {
width: 34rpx;
height: 34rpx;
margin-right:20rpx;
margin-top: 15rpx;
}
子组件的js
简单说明一下:
父组件传过来的分别是总共的数据:list,实际值(对应展示下拉的id):actualvalue 展示下拉的值: showvalue 进入页面时候的摊位号:stall
子组件中输入框输入的值进行筛选,list数组过滤出来后返回给list2进行展示,下拉框选择事件触发,获取到选中的选项的id和显示值,显示值picker_value进行显示,id便于传入到后台,这个项目这边因为摊位号字段不是很复杂且唯一,就用摊位号即可。
子组件再把刚刚选中的选项的id值传给父组件,用bind:action 自定义事件即可。
Component({
/**
* 组件的属性列表
*/
properties: {
list: {//下拉框数据来源
type: [Array, Object],
value: listvalue,
description: '数据源',
observer(newVal, oldVal) {
this.setData({
list: newVal,
list2: newVal
})
}
},
_width: {//组件宽度
type: String,
value: "100rpx"
},
_height: {//组件高度
type: String,
value: "100rpx"
},
actualvalue: { //实际值
type: String,
value: "id"
},
showvalue: { //显示值
type: String,
value: "name"
},
stall :{
type: String,
}
},
/**
* 组件的初始数据
*/
data: {
picker_value: '',//输入框值
index: 0,//下拉框下标
list2: []//下拉框数据
},
created(e) {
_self = this;
},
/**
* 组件的方法列表
*/
methods: {
//文本框输入事件
bindkeyinput(e) {
const _value = e.detail.value;
const _showvalue2 = this.data.showvalue;
const _list = JSON.parse(JSON.stringify(this.data.list));
const array = _list.filter(item => item[_showvalue2].indexOf(_value) != -1).map(item => {
const result = JSON.parse(JSON.stringify(item));
return result;
})
this.setData({
list2: array
})
},
//下拉框选择事件
bindchange(e) {
const _idx = e.detail.value;
const _showvalue = this.data.showvalue;
const _actualvalue = this.data.actualvalue;
const list2_value = this.data.list2[_idx][_actualvalue];
this.setData({
index: _idx,
list2: this.data.list,
picker_value: this.data.list2[_idx][_showvalue]
})
this.fun(list2_value);
},
fun(list2_value) {
this.triggerEvent("action", {
id: list2_value
});
}
}
})