需求:
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í)行堡僻。
真的是太方便啦~~~~