微信小程序如何自定义一个可输入筛选的下拉弹出框,也封装成组件。

在开发过程中,经常会遇到下拉框,有些时候内容过多,找起来也不方便,给他增加一个输入框,相当于用户输入某些信息,然后再下拉,符合输入内容的数据将会被展示出来,大大方便了用户操作体验。

话不多说,让我们开始吧!
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}}">&nbsp;&nbsp;&nbsp;</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
      });
    }
  }
})

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值