美文网首页APP & program
微信小程序组件:下拉框

微信小程序组件:下拉框

作者: 牛会骑自行车 | 来源:发表于2022-05-01 15:29 被阅读0次

需求:
1.调取接口获取下拉框数据
2.下拉框分页
3.可以通过输入框进行数据搜索
4.输入框可以清空
5.可选是否展示第一条数据
6.根据输入框所在位置判断下拉框出现的位置
7.聚焦时的样式变化

思路:
1.将接口所需参数传值进组件
2.与上篇文章的列表方式一致
3.bindinput时取输入框的值传入接口参数中同时调取数据
4.没啥好说的
5.同上
6.输入框位于整个页面中线以上就让下拉框出现在输入框下面,反之则。。反之
7.依旧没啥好说的。。

效果图 👇

那啥我感到非常抱歉哈哈哈哈哈哈
这个组件有个小小的问题,我使用了animation,用opacity来控制的下拉框显隐。很明显会存在一个问题就是当它看不到的时候还是会存在啊哈哈哈哈哈哈哈哈真是智障但是我懒得粘代码了。。遇到这个问题的时候再多一个变量加在z-index上就可以啦
真的很抱歉哟

上代码 👇
组件html ↓

<!--components/form/select.wxml-->

<view class="f_r_b select-con form-con" style="border: 2rpx solid {{active ? '#416BFF' : '#EEEEEE'}};" id="select">

  <input class="input" type="text" value="{{value}}" bindinput="onChange" bindfocus="onFocus" bindblur="onBlur"
    disabled="{{disabled}}" />
  <!-- 清空按钮的小叉 -->
  <image src="/images/common/icon_close.png" class="icon" catchtap="onClear" wx:if="{{clearShow}}"></image>
  <!-- 右侧的小箭头 -->
  <image src="{{active ? '/images/common/icon_form_arrow_up_active.png' : '/images/common/icon_arrow_down.png'}}" class="icon" wx:if="{{disabled?false:true}}"></image>
  <!-- 下拉框 -->
  <scroll-view class="option-con" style="top: {{optionTop}};bottom: {{optionBottom}};opacity: 0;" scroll-y
    animation="{{listShow}}" show-scrollbar="{{false}}" enhanced bindscrolltolower="moreData" id="list">
    <view class="item" wx:for="{{options}}" wx:key="index" bindtap="clickRow" data-item="{{item}}">
      {{item[showName]}}
    </view>
    <view class="loading">
      {{bottomText}}
    </view>
  </scroll-view>

</view>

组件js ↓

// components/form/select.js

Component({
  properties: {
    options: Array,
    // 接口相关的参数 ↓
    interface: {
      type: Object,
        value: () => {
          return {
            url: "", // 路径
            method: "", // 方法
            params: {} // 参数
          }
        }
    },
    // 搜索框的参数名  ↓
    inputName: String,
    // 选中展示的参数名  ↓
    showName: {
      type: String,
      value: "name"
    },
    // 是否展示第一条数据  ↓
    showFirstData: {
      type: Boolean,
      value: false
    },
    // 调取接口的信号??大概就这意思。。重置也用这个参数来着哈哈哈哈哈
    signal: Boolean,
  },
  data: {
    clearShow: false, // 清除数据的icon小×
    bottomText: "加载中...", // 下拉框底部的文字 ‘加载中’、‘到底啦~’
    currentCount: 0,
    value: "", // 搜索框的值
    firstGetData: false, // 是否第一次调取数据
    active: false
  },
  observers: {
    "signal": function (v) {
      if (!v) return;
      this.setData({
        value: "",
        ['interface.params.pageNum']: 1,
        [`interface.params.${this.data.inputName}`]: '',
        firstGetData: false
      })
      this.getData();
    },
    "value": function (v) {
      // 写不动注释了。。。。。。自己对比html就能懂这句
      this.setData({
        clearShow: v === '' ? false : true
      })
    },
  },
  methods: {
    getData() {
      // 接收接口需要的参数
      const {
        url,
        params,
        method
      } = this.data.interface;
      // 赋值是否第一次调取数据
      let gotFirstData = this.data.firstGetData;

      this.setData({
        // 给底部的文字赋值
        bottomText: "加载中..."
      })
      // 已经封装好的调取接口的方法,对应参数用wx.request也可
      wx.httpWithoutToken(url, params, method).then(res => {
        // 判断数据是否为空
        let hasData = res.content.length > 0 || res.content != '[]';

        if (res.code === 200 && res.success && hasData) {
          this.setData({
            // 页码最大值
            maxPage: res.totalCount / this.data.interface.params.pageSize,
            // 第一次调取数据赋值
            firstGetData: true
          })

          let params = this.data.interface.params;
          // 取值:已经调取过几页
          let used = (params.pageNum - 1) * params.pageSize;
          // 当前数据数
          let currentCount;
          // 赋值:下拉框数据
          res.content.forEach((option, index) => {
            this.setData({
              [`options[${used + index}]`]: option
            })
            currentCount = used + index + 1;
          })
          if (!gotFirstData) this.setFirstData(); // 第一次获取数据
          // 赋值:底部文字 --> 如果当前数据 <= 总数据数,则为‘加载中’
          this.setData({
            bottomText: currentCount < res.totalCount ? '加载中...' : '暂无更多数据'
          })
        } else {
          this.setData({
            bottomText: "暂无更多数据"
          })
        }
      })
    },
    moreData() {
      // 写不动注释了。。。。这里的代码可以参考“列表组件”
      let num = this.data.interface.params.pageNum;
      if (num >= this.data.maxPage) {
        this.setData({
          bottomText: "暂无更多数据"
        })
        return;
      }
      num++;
      this.setData({
        ['interface.params.pageNum']: num
      })
      this.getData();
    },
    // 如果需要设置默认选中第一条数据才会用到这个方法  ↓
    setFirstData() {
      // 多条数据  设置第一条数据
      if (this.data.showFirstData) {
        // value show 
        this.setData({
          value: this.data.options[0][this.data.showName]
        })
        // send value to page
        this.triggerEvent("showDefaultValue", this.data.options[0]);
      }
    },
    onChange(e) {
      // input的change事件
      let val = e.detail.value;
      this.setData({
        value: e.detail.value,
        [`interface.params.${this.data.inputName}`]: val,
        [`interface.params.pageNum`]: 1,
        options: []
      })
      this.getData();
    },
    onFocus() {
      this.setData({
        active: true
      })
      // 获取input-con的位置,判断drop-con的弹出方向
      wx.getDomInfo(this, 'select').then(res => {
        let containerHeight = res[1].scrollHeight;
        let offsetTop = res[0].top;
        let num = offsetTop / containerHeight;

        if (num * 10 <= 5) {
          this.setData({
            optionTop: "72rpx",
            optionBottom: ""
          })
        } else {
          this.setData({
            optionBottom: "73rpx",
            optionTop: ""
          })
        }
      })

      this.handleListShow(true);
    },
    onBlur() {
      this.setData({
        active: false
      })
      setTimeout(() => {
        this.handleListShow(false);
      }, 1);
    },
    clickRow(e) {
      // 取值:点击每行
      let item = e.currentTarget.dataset.item;
      this.setData({
        value: item.name,
        [`interface.params.pageNum`]: 1,
        [`interface.params.${this.data.inputName}`]: item[`${this.data.showName}`],
        options: []
      })
      this.getData();

      this.triggerEvent("select", item);
    },
    // 点击输入框右侧的清空按钮  ↓
    onClear() {
      this.setData({
        value: '',
        [`interface.params.${this.data.inputName}`]: '',
        [`interface.params.pageNum`]: 1,
        options: []
      })
      this.triggerEvent("select", "");
      this.getData();
    },
    // drop-con show situation:下拉框展开或收起时的方法。
    // 有动画的这么写,如果只是控制显隐就给wx:if赋值true or false即可
    handleListShow(show) {
      let opacity = show ? 1 : 0;
      this.listShow.opacity(opacity).step()
      this.setData({
        listShow: this.listShow.export()
      })
    },
  },
  lifetimes: {
    attached() {
      // 下拉框显隐的动画:我这个是用透明度来做的
      this.listShow = wx.createAnimation({
        duration: 100
      })
    },
  },
})

使用页面 👇 (JSON文件先引用这个组件昂,代码懒得粘了)
html ↓

  <select interface="{{interface}}" signal="{{signal}}" inputName="name"  showFirstData 
  bindselect="handleChooseAgency" bindshowDefaultValue="agencyFirstValue"></select>

js ↓

  data: {
    interface: {},
    signal: false
  },
  initSelect() {
    this.setData({
      'interface': {
        url: "selectMechanismByCode",
        method: "GET",
        params: {
          pageNum: 1,
          pageSize: 8,
          name: "",
        }
      },
      signal: true
    })
  },
  handleChooseAgency(e) {
    let item = e.detail;
    console.log(item,'取值每行数据')
  },
  agencyFirstValue(e) {
    let firstAgency = e.detail;
    console.log(firstAgency,'取值默认赋值第一个的数据')
  },
  onLoad: function () {
    this.initSelect();
  },

微信小程序与vue很像,不过在监听数据这方面,vue的watch只会在监听到变化的时候才会执行,但小程序好像只要赋值,就算与以前的值一样,也会执行。
在这个case中,signal的设置就是运用了这一点。不论是初始化页面,还是刷新后重置页面数据,只要将signal赋值true就可以执行。
真的是太方便啦~~~~

相关文章

  • 小程序好文集合

    组件篇 微信小程序:组件实践 整体梳理 微信小程序开发深入解读

  • 微信小程序-canvas压缩图片使用入门

    微信小程序canvas组件官方文档 微信小程序canvas组件官方文档canvas API canvas组件介绍 ...

  • 微信小程序日历组件开发

    # 微信小程序日历组件开发 微信小程序基础知识 微信小程序 框架介绍 组件文档 上述是开发小程序的基本知识。 今天...

  • 微信小程序基础

    微信小程序介绍微信小程序开发工具的使用微信小程序框架文件微信小程序逻辑层微信小程序视图层微信小程序组件介绍微信小程...

  • 微信小程序组件:下拉框

    需求:1.调取接口获取下拉框数据2.下拉框分页3.可以通过输入框进行数据搜索4.输入框可以清空5.可选是否展示第一...

  • 微信小程序组件探究和应用

    把玩微信小程序组件 微信小程序把玩《二》:页面生命周期,模块化,数据绑定,view组件 微信小程序把玩《三》:sc...

  • 微信小程序性能优化实践

    历史回顾: 微信小程序自定义组件 - 表格组件来啦 通过微信小程序来实现 “钉钉打卡” 记一次微信小程序项目分包,...

  • 微信小程序组件化开发

    什么是组件化开发 微信小程序的组件和Vue的组件非常相似。 在微信小程序中有很多内置组件,比如button vie...

  • 小程序tab组件封装

    微信小程序tab组件封装 最近在做微信小程序的项目,下面就微信小程序中tab的tab功能封装成一个组件,在项目项需...

  • 微信小程序细节1(icon的使用)

    微信小程序官网地址如下:(11月3号晚10点之后微信小程序开始公测,但不支持发布) 微信小程序 微信小程序的组件-...

网友评论

    本文标题:微信小程序组件:下拉框

    本文链接:https://www.haomeiwen.com/subject/pfssyrtx.html