微信小程序組件:下拉框

需求:
1.調(diào)取接口獲取下拉框數(shù)據(jù)
2.下拉框分頁
3.可以通過輸入框進行數(shù)據(jù)搜索
4.輸入框可以清空
5.可選是否展示第一條數(shù)據(jù)
6.根據(jù)輸入框所在位置判斷下拉框出現(xiàn)的位置
7.聚焦時的樣式變化

思路:
1.將接口所需參數(shù)傳值進組件
2.與上篇文章的列表方式一致
3.bindinput時取輸入框的值傳入接口參數(shù)中同時調(diào)取數(shù)據(jù)
4.沒啥好說的
5.同上
6.輸入框位于整個頁面中線以上就讓下拉框出現(xiàn)在輸入框下面袭异,反之則吼砂。。反之
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>
  <!-- 右側(cè)的小箭頭 -->
  <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,
    // 接口相關(guān)的參數(shù) ↓
    interface: {
      type: Object,
        value: () => {
          return {
            url: "", // 路徑
            method: "", // 方法
            params: {} // 參數(shù)
          }
        }
    },
    // 搜索框的參數(shù)名  ↓
    inputName: String,
    // 選中展示的參數(shù)名  ↓
    showName: {
      type: String,
      value: "name"
    },
    // 是否展示第一條數(shù)據(jù)  ↓
    showFirstData: {
      type: Boolean,
      value: false
    },
    // 調(diào)取接口的信號怎顾?读慎?大概就這意思。槐雾。重置也用這個參數(shù)來著哈哈哈哈哈
    signal: Boolean,
  },
  data: {
    clearShow: false, // 清除數(shù)據(jù)的icon小×
    bottomText: "加載中...", // 下拉框底部的文字 ‘加載中’夭委、‘到底啦~’
    currentCount: 0,
    value: "", // 搜索框的值
    firstGetData: false, // 是否第一次調(diào)取數(shù)據(jù)
    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() {
      // 接收接口需要的參數(shù)
      const {
        url,
        params,
        method
      } = this.data.interface;
      // 賦值是否第一次調(diào)取數(shù)據(jù)
      let gotFirstData = this.data.firstGetData;

      this.setData({
        // 給底部的文字賦值
        bottomText: "加載中..."
      })
      // 已經(jīng)封裝好的調(diào)取接口的方法,對應參數(shù)用wx.request也可
      wx.httpWithoutToken(url, params, method).then(res => {
        // 判斷數(shù)據(jù)是否為空
        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,
            // 第一次調(diào)取數(shù)據(jù)賦值
            firstGetData: true
          })

          let params = this.data.interface.params;
          // 取值:已經(jīng)調(diào)取過幾頁
          let used = (params.pageNum - 1) * params.pageSize;
          // 當前數(shù)據(jù)數(shù)
          let currentCount;
          // 賦值:下拉框數(shù)據(jù)
          res.content.forEach((option, index) => {
            this.setData({
              [`options[${used + index}]`]: option
            })
            currentCount = used + index + 1;
          })
          if (!gotFirstData) this.setFirstData(); // 第一次獲取數(shù)據(jù)
          // 賦值:底部文字 --> 如果當前數(shù)據(jù) <= 總數(shù)據(jù)數(shù)鸠儿,則為‘加載中’
          this.setData({
            bottomText: currentCount < res.totalCount ? '加載中...' : '暫無更多數(shù)據(jù)'
          })
        } else {
          this.setData({
            bottomText: "暫無更多數(shù)據(jù)"
          })
        }
      })
    },
    moreData() {
      // 寫不動注釋了屹蚊。。进每。汹粤。這里的代碼可以參考“列表組件”
      let num = this.data.interface.params.pageNum;
      if (num >= this.data.maxPage) {
        this.setData({
          bottomText: "暫無更多數(shù)據(jù)"
        })
        return;
      }
      num++;
      this.setData({
        ['interface.params.pageNum']: num
      })
      this.getData();
    },
    // 如果需要設置默認選中第一條數(shù)據(jù)才會用到這個方法  ↓
    setFirstData() {
      // 多條數(shù)據(jù)  設置第一條數(shù)據(jù)
      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);
    },
    // 點擊輸入框右側(cè)的清空按鈕  ↓
    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,'取值每行數(shù)據(jù)')
  },
  agencyFirstValue(e) {
    let firstAgency = e.detail;
    console.log(firstAgency,'取值默認賦值第一個的數(shù)據(jù)')
  },
  onLoad: function () {
    this.initSelect();
  },

微信小程序與vue很像贤徒,不過在監(jiān)聽數(shù)據(jù)這方面芹壕,vue的watch只會在監(jiān)聽到變化的時候才會執(zhí)行汇四,但小程序好像只要賦值,就算與以前的值一樣哪雕,也會執(zhí)行船殉。
在這個case中,signal的設置就是運用了這一點斯嚎。不論是初始化頁面利虫,還是刷新后重置頁面數(shù)據(jù),只要將signal賦值true就可以執(zhí)行堡僻。
真的是太方便啦~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末糠惫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子钉疫,更是在濱河造成了極大的恐慌硼讽,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牲阁,死亡現(xiàn)場離奇詭異固阁,居然都是意外死亡,警方通過查閱死者的電腦和手機城菊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門备燃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凌唬,你說我怎么就攤上這事并齐。” “怎么了客税?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵况褪,是天一觀的道長。 經(jīng)常有香客問我更耻,道長测垛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任酥夭,我火速辦了婚禮赐纱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘熬北。我一直安慰自己疙描,他們只是感情好,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布讶隐。 她就那樣靜靜地躺著起胰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上效五,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天地消,我揣著相機與錄音,去河邊找鬼畏妖。 笑死脉执,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的戒劫。 我是一名探鬼主播半夷,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼迅细!你這毒婦竟也來了巫橄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤茵典,失蹤者是張志新(化名)和其女友劉穎湘换,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體统阿,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡彩倚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扶平。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片署恍。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜻直,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情袁串,我是刑警寧澤概而,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站囱修,受9級特大地震影響赎瑰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜破镰,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一餐曼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲜漩,春花似錦源譬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喉祭,卻和暖如春养渴,著一層夾襖步出監(jiān)牢的瞬間雷绢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工理卑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翘紊,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓藐唠,卻偏偏與公主長得像帆疟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子中捆,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容